题意:n个字母排序,给定m个关系,输出
①在得到几个关系后确定排序(全序)
②在得到几个关系后出现矛盾,有环
③不能得到确定的排序(偏序)
思路:直白的拓扑排序,但很多要注意的地方
1)每读入一个关系做一次拓扑排序
找入度为0点u,确定位置,使u指向的点的入度减1,再找入度为0的点...
未排完序就找不到入度为0的点则有环,找到入度为0的点多于1个则关系不能确定
2)在可以确定①②两种情况后不再考虑后面的输入(我觉得确定了①之后还应该看看会不会②的,但看别人的题解都没有,自己加了一下看看,wa了)
3)拓扑排序时发现了不能确定关系后不能返回,继续操作可能发有环
#include
#include
#include
using namespace std;
int n, m;
int list[30][30], in1[30], in2[30], vis[30];
int ans[30];
int toposort()
{
memset(vis, 0, sizeof(vis));
int flag = 2;
for(int i = 0; i < n; i++)
in2[i] = in1[i];
for(int i = 0; i < n; i++)
{
int in0 = 0, u;
for(int j = 0; j < n; j++)
{//求入度为0的点,in0记录个数
if(!vis[j] && !in2[j])
{
in0++; u = j;
}
}
if(!in0) return 1;
if(in0 > 1) flag = 0; //标志不能确定排序但不返回
vis[u] = 1; ans[i] = u;
for(int j = 0; j < n; j++)
{
if(list[u][j]) in2[j]--;
}
}
return flag;
}
int main()
{
#ifdef LOCAL
freopen("data.in", "r", stdin);
#endif
char s[5];
int inconsis, determind;
while(scanf("%d%d", &n ,&m) != EOF)
{
if(!n && !m) break;
memset(in1, 0, sizeof(in1));
memset(list, 0, sizeof(list));
inconsis = 0; determind = 0;
for(int i = 1; i <= m; i++)
{
scanf("%s", s);
if(inconsis || determind) continue;
//(尝试确定排序后仍考虑之后的输入) if(inconsis) continue;
int a = s[0] - 'A', b = s[2] - 'A';
if(!list[a][b])
{
in1[b]++; list[a][b] = 1;
}
int topo = toposort();
if(topo == 1)
{
printf("Inconsistency found after %d relations.\n", i);
inconsis = 1;
}
if(topo == 2 ) //(尝试确定排序后仍考虑之后的输入)&& !determind)
{
printf("Sorted sequence determined after %d relations: ", i);
for(int j = 0; j < n; j++)
printf("%c", ans[j] + 'A');
printf(".\n");
determind = i;
}
}
/*(尝试确定排序后仍考虑之后的输入)
if(!inconsis && determind)
{
printf("Sorted sequence determined after %d relations: ", determind);
for(int j = 0; j < n; j++)
printf("%c", ans[j] + 'A');
printf(".\n");
}*/
if(!inconsis && !determind)
printf("Sorted sequence cannot be determined.\n");
}
return 0;
}