題目鏈接:
http://poj.org/problem?id=1094
題目大意:
這個題目的難點就在於題目意思的理解。
有n個大寫字母,並且告訴這n個大寫字母的大小關係,要你對這n個大寫字母進行排序。
解題思路:
但是,這個題目並不是等所有的輸入結束之後判斷,而是一邊輸入一邊進行判斷。
每次輸入一組字母的關係之後,我們就需要更新原來的圖。
如果原來的圖已經能夠確定一個排序或者已經能夠確定不能排序,那麼就不用進行排序了。
如果原來的圖不能確定一個排序,那麼進行一次拓撲排序。
拓撲排序之後,如果出現了環,則說明找不到這樣的一個拓撲排序。
如果這個時候已經可以將所有的字母排序了,那麼餘下的那些字母關係我們不需要再理會。
但是最後一定要記得把所有的輸入都讀進去。
源代碼:
#include<stdio.h>
#include<stdlib.h>
#include<string>
#include<string.h>
#include<math.h>
#include<cmath>
#include<vector>
#include<map>
#include<iostream>
#include<algorithm>
using namespace std;
int s[27][27];
int key[27];
int d[27]; //記錄下每個點的度數
int d1[27]; //暫時存儲每個點的度數
int flag,n,m,ans;
void top_order() //拓撲排序
{
int i,j,k,cnt,cc;
cc=0;
for(i=1;i<=n;i++)
{
d1[i]=d[i];
// printf("%d\n",d1[i]);
}
for(i=1;i<=n;i++) //尋找第1個點
{
cnt=0;
for(j=1;j<=n;j++)
{
if(d1[j]==0)
{
cnt++;
k=j;
}
}
if(cnt==0) //沒有解的情況
{
flag=1;
break;
}
if(cnt==1) cc++;
d1[k]=-1;
key[i]=k;
for(j=1;j<=n;j++)
if(s[k][j])
d1[j]--;
}
if(cc==n) flag=2;
return;
}
int main()
{
freopen("in.txt","r",stdin);
int a,b,i,j;
char x,y;
while(scanf("%d%d",&n,&m)==2 && n+m)
{
getchar();
memset(s,0,sizeof(s));
memset(d,0,sizeof(d));
memset(key,0,sizeof(key));
ans=0;
flag=0; //初始化爲2,是因爲沒有輸入的時候是不能確定排序的
for(i=1;i<=m;i++) //每輸入一組解就對該圖進行一次拓撲排序,如果出現環或者排序已經出來了,則可以輸出最後結果
{
scanf("%c<%c",&x,&y);
a=x-64;
b=y-64;
getchar();
if(a==b) //去掉自環的情況
flag=1;
if(!s[a][b]) //可能出現重邊
{
s[a][b]=1;
d[b]++;
}
if(flag==0) //前一狀態的圖還不能確定一個排序,進行進一步的排序
top_order();
if(flag==1)
{
if(!ans) ans=i;
continue; //出現了環,不往下做,但是數據必須輸入完
}
if(flag==2)
{
if(!ans) ans=i;
continue; //已經能得到一個唯一的拓撲排序了,不往下做了
}
}
if(flag==1) //出現了環的情況
{
printf("Inconsistency found after %d relations.\n",ans);
}
else if(flag==0) //有多種解的情況
{
printf("Sorted sequence cannot be determined.\n");
}
else if(flag==2) //只有唯一解的情況
{
printf("Sorted sequence determined after %d relations: ",ans);
for(i=1;i<=n;i++)
printf("%c",key[i]+64);
printf(".\n");
}
}
return 0;
}