传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1811
解题思路:
主要利用了:
并查集,合并关系是a=b的情况,注意在合并的时候要以大的为树根,也就是向编号大的合并。
然后利用拓扑排序,进行关系的判断。用L表示度为0的点,如果在同一时刻度数为零的点有多个,这就是“NUCERTAIN”情况。
如在存在回路,则说明存在“CONFILICT”。
实现代码:
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <vector> using namespace std; const int maxn=10010; struct Edge{ int u,v; char s[4]; }edges[maxn*2]; vector<int>G[maxn]; int deg[maxn]; int fa[maxn]; int num=0; bool crt; void init(int n){ crt=true; num=n; for(int i=0;i<n;i++){ deg[i]=0; fa[i]=i; G[i].clear(); } } int findfa(int u){ if(fa[u]!=u) fa[u]=findfa(fa[u]); return fa[u]; } void unit(int u,int v) { int fau =findfa(u); int fav =findfa(v); if(fau==fav) return; if(fau<fav) { fa[fav] =fau; }else{ fa[fau] =fav; } num--; } void toplogic(int n){ queue<int> q; for(int i=0;i<n;i++){ if(!deg[i]&&fa[i]==i) q.push(i); } while(!q.empty()){ if(q.size()>1){ crt=false; } int u=q.front(); q.pop(); num--; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(!--deg[v]){ q.push(v); } } } } int main(){ int N,M; while(scanf("%d%d",&N,&M)!=EOF){ init(N); for(int i=0;i<M;i++){ scanf("%d%s%d",&edges[i].u,edges[i].s,&edges[i].v); if((edges[i].s)[0]=='=') unit(edges[i].u,edges[i].v); } for(int i=0;i<M;i++){ int fu=findfa(edges[i].u); int fv=findfa(edges[i].v); if((edges[i].s)[0]=='>'){ G[fu].push_back(fv); deg[fv]++; }else if((edges[i].s)[0]=='<'){ G[fv].push_back(fu); deg[fu]++; } } toplogic(N); if(num>0) puts("CONFLICT"); else if (!crt) puts("UNCERTAIN"); else puts("OK"); } return 0; }