题目链接:Click here~~
题意:
中文题啊中文题。
解题思路:
此题关键的一点是要意识到排序时,Rating相同的人一定排列在一起,且顺序一定存在。
故可以用并查集先将数据中Rating相同的人看做一个集合,然后将各个集合拓扑排序。
接下来就是对于拓扑排序的理解了,当找不到入度为0的点时,图中有环,故会出现冲突。
当每次找到入度为0的点大于1个的时候,说明有多种排序方式,即信息不全。
ps:做完这道题,对拓扑排序的理解又加深了些,话说又不小心进rank了,哎,这rp。
#include <queue> #include <stdio.h> #include <string.h> using namespace std; #define N 10005 #define FileIn freopen("in.ads","r",stdin) #define FileOut freopen("Wa.ads","w",stdout) struct T { int v,next; }E[N+N]; struct TT { int head,rd; }V[N]; int top,ans,cnt,n,m; int pre[N]; bool Uncertain; int Root(int x) { if(pre[x] == -1) return x; else pre[x] = Root(pre[x]); } void Add_Edge(int u,int v) { E[top].v = v; E[top].next = V[u].head; V[u].head = top++; ++V[v].rd; } bool Top_Sort() { queue<int> Q; Uncertain = false; for(int i=1;i<=n;i++) if(V[i].rd == 0 && i == Root(i)) //the key Q.push(i); while(!Q.empty()) { ++cnt; if(Q.size() > 1) //the details Uncertain = true; int p = Q.front(); //printf("p->%d\n",p-1); for(int i=V[p].head;i!=NULL;i=E[i].next) { int q = E[i].v; if(--V[q].rd == 0) Q.push(q); } Q.pop(); } return cnt == n; } int main() { //FileIn;FileOut; int u[N],v[N]; char c[N]; while(~scanf("%d%d",&n,&m)) { memset(V,0,sizeof(V)); memset(pre,-1,sizeof(pre)); top = 1; ans = cnt = 0; Uncertain = false; for(int i=0;i<m;i++) { scanf("%d %c %d",&u[i],&c[i],&v[i]); ++u[i],++v[i]; if(c[i] == '=') { int r1 = Root(u[i]); int r2 = Root(v[i]); //printf("r1->%d,r2->%d\n",r1,r2); if(r1 != r2) { pre[r1] = r2; ++cnt; } } } for(int i=0;i<m;i++) { int r1 = Root(u[i]); int r2 = Root(v[i]); //printf("%d's ->r1->%d ,%d's ->r2->%d\n",u[i]-1,r1-1,v[i]-1,r2-1); switch(c[i]) { case '>': if(r1 == r2) goto end; else Add_Edge(r1,r2); break; case '<': if(r1 == r2) goto end; else Add_Edge(r2,r1); break; } } if(!Top_Sort()) end: puts("CONFLICT"); else puts(Uncertain ? "UNCERTAIN" : "OK"); } return 0; }