http://poj.org/problem?id=1094
拓扑排序,有点坑。。
给出m个关系,在输入的同时判断在当前条件下是否有环,是否能形成唯一拓扑序列,或者是不确定。
此题要注意优先级,当在输入的过程中出现环或拓扑排序成功时可以直接输出,但当前驱结点不唯一时不能直接输出,因为后面的输入可能导致出现环,这时候就应该输出矛盾而不是拓扑序列不唯一了,所以判拓扑序列不唯一时应放在输入完毕后
#include<stdio.h>
#include<string.h>
int n,m,cnt;
int degree[30];
bool map[30][30];
char topo[30];
int toposort()
{
int indegree[30];//函数内部设一个记录入度的数组,尝试着进行拓扑;
int i,j,k,m;
for(i = 0; i < n; i++)
indegree[i] = degree[i];
cnt = 0;
m = 0;//判断是否有多个前驱结点,注意初始化放在外循环外面;
for(i = 0; i < n; i++)
{
for(j = 0; j < n; j++)
{
if(indegree[j] == 0)
{
topo[cnt++] = j+'A';//进拓扑序列;
indegree[j]--;
for(k = j+1; k < n; k++)
{
if(indegree[k] == 0)
m = 1;//m=1说明有多个前驱结点,拓扑序列不唯一;
}
for(k = 0; k < n; k++)
{
if(map[j][k] == 1)
indegree[k]--;//与j相连的结点入度减一;
}
break;
}
}
}
topo[cnt] = '\0';
if(cnt < n)
return -1;//若n次循环后前驱结点数小于n说明有环;
else if(m == 1) return 0;//m=1说明有多个前驱结点,拓扑序列不唯一;
else return 1;
}
int main()
{
int i,res;
char u,v;
while(~scanf("%d %d",&n,&m))
{
if(n == 0 && m == 0)
break;
getchar();
memset(map,0,sizeof(map));
memset(degree,0,sizeof(degree));
int ok = 0;
for(i = 1; i <= m; i++)
{
if(ok == 0)
{
scanf("%c<%c",&u,&v);
getchar();
degree[v-'A']++;
map[u-'A'][v-'A'] = 1;
res = toposort();
if(res == -1)
{
//有环时直接输出
printf("Inconsistency found after %d relations.\n",i);
ok = 1;
continue;
}
else if(res == 1)
{ //当只有一个前驱结点时才输出拓扑序列。
printf("Sorted sequence determined after %d relations: ",i);
printf("%s.\n",topo);
ok = 1;
continue;
}
}
else
{
scanf("%c<%c",&u,&v);
getchar();
}
}
if(ok == 0)
printf("Sorted sequence cannot be determined.\n");
}
return 0;
}