题意:给你字母表的前N个大写字母和M个大小关系所有的边按顺序给你,要你在能判断出全序或矛盾的时候及时输出答案,或者直到最后也不能出现全序。
思路:这道题卡在怎么在前K个已经能判断出全序了就输出,后来搜到了结论,如果能topo排序就说明没有矛盾,但是可能是全序或者偏序集.如果是全序集,那么topo排序的过程中,入度为0的点始终只会存在1个.
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <set>
#include <ctime>
#include <cmath>
#include <cctype>
using namespace std;
#define maxn 50
#define LL long long
int cas=1,T;
vector<int>G[maxn];
int in[maxn];
int n,m;
char order[1000][10];
char ans[maxn];
int cnt;
int topo()
{
cnt=0;
queue<int>q;
int ind[maxn];
memcpy(ind,in,sizeof(in));
bool flag=1;
for (int i = 0;i<n;i++)
if (ind[i]==0)
q.push(i);
while (!q.empty())
{
if (q.size()>1) //q中始终只有一个元素才能保证全序
flag=0;
int u = q.front();q.pop();
ans[cnt++]=u+'A';
for (int i = 0;i<G[u].size();i++)
{
int v = G[u][i];
if (--ind[v]==0)
q.push(v);
}
}
int result=0;
if (cnt < n)
result = -1; //存在环
else if (flag)
result = 1; //已经全序
return result;
}
int main()
{
while (scanf("%d%d",&n,&m)!=EOF && n)
{
memset(in,0,sizeof(in));
for (int i = 0;i<n;i++)
G[i].clear();
for (int i = 0;i<m;i++)
scanf("%s",order[i]);
int flag = 0;
int i;
for (i = 0;i<m;i++)
{
int u = order[i][0]-'A';
int v = order[i][2]-'A';
G[u].push_back(v);
in[v]++;
if ((flag = topo()) !=0)
break;
}
ans[n]=0;
if (flag==1)
printf("Sorted sequence determined after %d relations: %s.\n",i+1,ans);
else if (flag ==0)
printf("Sorted sequence cannot be determined.\n");
else
printf("Inconsistency found after %d relations.\n",i+1);
}
//freopen("in","r",stdin);
//scanf("%d",&T);
//printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
return 0;
}