拓扑排序难题。
对于相同排名的玩家,我们将他们组成一个集合。这可以用并查集实现。
然后将并查集看成一个点,将所有大于小于的关系转换成集合中的关系,这个过程就可以判断方案是否冲突了。
然后拓扑排序求排名,顺便也就可以判断结果是否唯一了。
#include <cstdio> #include <algorithm> #include <iostream> #include <cctype> #include <queue> #include <cstring> #include <queue> using namespace std; #define rep(i, l, r) for(int i=l; i<=r; i++) #define travel(x) for(edge *p=fir[x]; p; p=p->n) #define maxn 10009 #define maxm 20009 #define clr(x, c) memset(x, c, sizeof(x)) struct edge{int x, y, z; edge *n;} e[maxm], *fir[maxn], *pt; int n, m, a, b, v[maxn], h[maxn], die; char s[10]; inline void Init(){pt=e; clr(fir, 0); clr(v, 0); die=0; rep(i, 0, n-1) h[i]=i;} inline void Add(int x, int y, int z){pt->x=x, pt->y=y, pt->z=z, pt++;} int Find(int x){return x==h[x]?x:h[x]=Find(h[x]);} int main() { while (~scanf("%d%d", &n, &m)) { Init(); rep(i, 0, m-1) { scanf("%d%s%d", &a, s, &b); if (s[0]==‘=‘) Add(max(a, b), min(a, b), 0); else if (s[0]==‘>‘) Add(a, b, 1); else if (s[0]==‘<‘) Add(b, a, 1); } rep(i, 0, m-1) if (!e[i].z) Find(e[i].x)!=Find(e[i].y) ? h[h[e[i].x]]=h[e[i].y] : i=i; rep(i, 0, n-1) Find(i); priority_queue<int>q; rep(i, 0, m-1) if (e[i].z) e[i].x=h[e[i].x], e[i].y=h[e[i].y]; rep(i, 0, m-1) if (e[i].z) v[e[i].y]++; rep(i, 0, m-1) if (e[i].z) e[i].n=fir[e[i].x], fir[e[i].x]=&e[i]; rep(i, 0, n-1) if (h[i]==i && !v[i]) q.push(i); while (!q.empty()) { if (q.size()>1) die=2; int x=q.top(); q.pop(); v[x]=-1; travel(x) if (p->z) {v[p->y]--; if (!v[p->y]) q.push(p->y);} } rep(i, 0, n-1) if (h[i]==i && v[i]!=-1) {die=1; break;} if (die==0) printf("OK\n"); else if (die==1) printf("CONFLICT\n"); else printf("UNCERTAIN\n"); } }
原文:http://www.cnblogs.com/NanoApe/p/4445331.html