拓撲排序_Poj_1094

/*
文章大意是將n個字母排序(n<=26)。
最終必須排成鏈表式的輸出
一旦確定或者出現環,記錄當前步數,後續輸入無視
*/
/*
加個拓撲排序判斷圖的總結:
1、如果輸入的有向圖中的點,不存在入度爲0的點,則存在迴路,反過來則不成立
2、如果入隊的點的個數小於輸入的點的個數,則肯定存在迴路
3、如果存在的入度爲零的點大於一個,則肯定不存在一個可以確定的序列

*/

//解法1:拓撲排序解法

#include<iostream>
#include<vector>
#include<string>
#include<queue>
#include<list>

using namespace std;

#define UnSure 0 //不確定
#define Cycle 1//有環
#define Sorted 2//已排好序

int n;//輸入個數

vector<list<int> > g; // 圖
vector<int> top; //拓撲序列
vector<int> ins; //入度

//輔助變量
int i,j;

int topsort()
{
bool unsure = false;
queue<int> que;
vector<int> ins2(ins.begin(),ins.end());//建立入度副本
int u;
for(i=0;i<n;i++)
{
if(ins[i]==0) que.push(i);
}
list<int>::iterator it;
top.clear();
while(!que.empty())
{
if(que.size()!=1) unsure=true;
u=que.front(),que.pop();
top.push_back(u);
for(it=g[u].begin();it!=g[u].end();it++)
{
if(--ins2[*it]==0)
{
que.push(*it);
}
}
}
if(top.size()!=n) return Cycle;
else if(unsure) return UnSure;
return Sorted;
}

int main()
{
int m; //關係數
while(cin>>n>>m,m!=0||n!=0)
{
int steps = 0; //步數
int status = UnSure;//當前狀態
string rel;
   g.assign(n,list<int>());//建立相連表
ins.assign(n,0);//建立入讀表
int u,v;
for(steps=0;steps<m && status==UnSure;steps++)
{
cin>>rel;
u=int(rel[0]-'A'),v=int(rel[2]-'A');
if(find(g[u].begin(),g[u].end(),v)==g[u].end())//u,v邊未存在則插入鏈表
g[u].push_back(v),ins[v]++;
status = topsort();
}
for(i=steps;i<m;i++) cin>>rel;//處理無用的字符串
if(status == Sorted)
{
printf("Sorted sequence determined after %d relations: ",steps);
for(i=0;i<top.size();i++)
printf("%c",top[i]+'A');
printf(".\n");
}
else if(status == Cycle)
{
printf("Inconsistency found after %d relations.\n",steps);
}
else
{
printf("Sorted sequence cannot be determined.\n");
}
}
return 0;
}



//解法2:用二維數組實現記錄彼此之間的關係 

#include<iostream>
using namespace std;


int m,n;
int a[26][27];
bool b[26];
int i,j,l,x,y;
char k[4];
int suc,fail;
bool IsOk,_ok;


bool init()
{
//定義bool變量用來判斷是否成功
IsOk = true,_ok = false;
//初始化
suc=fail=-1;
memset(a,0,sizeof(a));
//輸入並初始化
for(i=0;i<n;i++)
{
scanf("%s",k);
if(IsOk&&!_ok)
{
x=k[0]-'A';
y=k[2]-'A';
a[x][y]=1;
if(a[y][x]==1)
{
IsOk = false;
fail = i;
}
if(IsOk)
{
//小於X的都小於Y 記錄下來
for(j=0;j<m;j++)
{
if(a[j][x])
{
a[j][y]=1;
if(a[y][j])
{
IsOk=false;
fail = i;
break;
}
}
}
//大於Y的都大於X,記錄下來
for(j=0;j<m;j++)
{
if(a[y][j])
{
a[x][j]=1;
if(a[j][x])
{
IsOk=false;
fail = i;
break;
}
}
}
}
if(!IsOk) continue;
if(!_ok)
{
//**每次輸入一次就判斷是否已經判斷完成**
//統計每行的數字
int sum;
for(j=0;j<m;j++)
{
sum=0;
for(l=0;l<m;l++)
{
sum+=a[j][l];
}
a[j][26]=sum;
}
//判斷每行的數字是不是都唯一。
memset(b,0,sizeof(b));//記錄是否已經訪問過
for(j=0;j<m;j++)
{
for(l=0;l<m;l++)
{
if(b[l]) continue;
else if(a[l][26]==j)
{
b[l]=true;
break;
}
}
if(l==m) break;//沒找到要的數字
}
if(j==m)
{
_ok=true;
suc=i;
}//成功
}
}
}
return IsOk;
}



int main()
{
while(scanf("%d%d",&m,&n)&&(m!=0||n!=0))
{
bool u = init();
if(u&&_ok)
{
//成功,則輸出
printf("Sorted sequence determined after %d relations: ",suc+1);
for(j=m-1;j>-1;j--)
{
for(l=0;l<m;l++)
{
if(a[l][26]==j)
{
printf("%c",'A'+l);
break;
}
}
}
printf(".\n");
}
else if(u)
{
printf("Sorted sequence cannot be determined.\n");
}
else
{
printf("Inconsistency found after %d relations.\n",fail+1);
}
}
return 0;
}

發佈了29 篇原創文章 · 獲贊 0 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章