链接:http://poj.org/problem?id=1094
大意就是给你一堆关系,让你判断什么时候能确定出这个序列,或者什么时候出现矛盾,又或者是不能确定的。
首先判断拓扑排序是否是确定的,就是判断在队列中的元素的个数是不是时刻都不大于一,如果是这就是确定的。
还有就是矛盾了,也就是判环,看入队的元素的个数是不是小于节点的个数,如果是那么就有环,因为有环的话,最后是找不到入度为零的节点的。
对于这道题来说因为他需要知道在那个关系给出时就能得到答案,所以不能确定的话一定是在所有都给出后,发现没有环,也不能确定,整个才是不能确定的。
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
#define M 10000
int indegree[M];
vector<int> G[M];
int mark[27];
int n,m;
queue<int> p;
int toposort()
{
while(!p.empty())
p.pop();
queue<int> q;
int flag = 1;
int temp[27];
int num = 0;
for(int i = 0;i < 26;i++)
{
if(mark[i])
{
num++;
temp[i] = indegree[i];
if(temp[i]==0)
q.push(i);
}
}
//cout << "front debug " << num << endl;
while(!q.empty())
{
//if(q.size()>1)
//{
//flag = 0;
//return 0;
//}
num--;
if(q.size()>1)
flag = 0;
int cur = q.front();
q.pop();
p.push(cur);
for(int i = 0;i < G[cur].size();i++)
{
//cout << "debug " << G[cur][i];
temp[G[cur][i]]--;
if(temp[G[cur][i]]==0)
{
q.push(G[cur][i]);
}
}
}
if(num>0) return -1; //有环
//cout << "this is debug" << p.size() << endl;
if(p.size()==n && flag==1) return 1;//确定
//cout << "debug " << num << endl;
return 0;
}
int main()
{
while(cin >> n >> m)
{
if(n==0 && m==0) break;
memset(mark,0,sizeof(mark));
memset(indegree,0,sizeof(indegree));
for(int i = 0;i < 26;i++)
G[i].clear();
int num = 0;
int sign = 0;
for(int i = 0;i < m;i++)
{
char s[5];
cin >> s;
if(sign) continue;
if(mark[s[0]-'A']==0)
mark[s[0]-'A'] = 1;
if(mark[s[2]-'A']==0)
mark[s[2]-'A'] = 1;
indegree[s[2]-'A']++;
G[s[0]-'A'].push_back(s[2]-'A');
int ans = toposort();
if(ans == -1)//有环
{
printf("Inconsistency found after %d relations.\n",i+1);
sign = 1;
}
if(ans == 1) //确定
{
printf("Sorted sequence determined after %d relations: ",i+1);
while(!p.empty())
{
int temp = p.front();
p.pop();
printf("%c",temp+'A');
}
printf(".\n");
sign = 1;
}
}
if(!sign)
{
printf("Sorted sequence cannot be determined.\n");
}
}
return 0;
}