hdu 1181(并查集+拓扑排序)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1811

思路:先处理‘=‘,全部合并为同一个节点,然后在拓扑排序就可以了。。。

拓扑排序知识:

*如果一次入队入度为零的点大于1则说明拓扑排序序列不唯一
*如果排序的总个数小于给定的个数,则说明存在回路

View Code
  1 #define _CRT_SECURE_NO_WARNINGS
  2 #include<iostream>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<vector>
  6 #include<queue>
  7 using namespace std;
  8 const int MAXN=10000+10;
  9 int parent[MAXN];
 10 int In[MAXN];
 11 vector<int>vet[MAXN];
 12 int n,m,num;
 13 struct Edge {
 14     int u,v;
 15     char ch;
 16 }edge[MAXN];
 17 
 18 
 19 void Initiate(){
 20     for(int i=0;i<n;i++){
 21         parent[i]=-1;
 22         vet[i].clear();
 23         In[i]=0;
 24     }
 25 }
 26 
 27 int Find(int x){
 28     int s;
 29     for(s=x;parent[s]>=0;s=parent[s]);
 30     while(s!=x){
 31         int tmp=parent[x];
 32         parent[x]=s;
 33         x=tmp;
 34     }
 35     return s;
 36 }
 37 
 38 void Union(int R1,int R2){
 39     int r1=Find(R1);
 40     int r2=Find(R2);
 41     if(r1!=r2){
 42         parent[r2]=r1;
 43     }
 44 }
 45 
 46 
 47 int main(){
 48     while(~scanf("%d%d",&n,&m)){
 49         Initiate();
 50         num=n;//总共要进行拓扑排序的n个点
 51         for(int i=0;i<m;i++){
 52             int u,v;
 53             scanf("%d %c %d",&edge[i].u,&edge[i].ch,&edge[i].v);
 54             if(edge[i].ch=='='){
 55                 Union(edge[i].u,edge[i].v);
 56                 num--;
 57             }
 58         }
 59         bool flag=true;
 60         for(int i=0;i<m;i++){
 61             if(edge[i].ch=='=')
 62                 continue;
 63             int r1=Find(edge[i].u);
 64             int r2=Find(edge[i].v);
 65             //如果找到了相等的,说明矛盾;
 66             if(r1==r2){
 67                 flag=false;
 68                 break;
 69             }
 70             if(edge[i].ch=='>'){
 71                 vet[r1].push_back(r2);
 72                 In[r2]++;
 73             }else if(edge[i].ch=='<'){
 74                 vet[r2].push_back(r1);
 75                 In[r1]++;
 76             }
 77         }
 78         if(!flag){
 79             puts("CONFLICT");
 80         }else {
 81             queue<int>Q;
 82             for(int i=0;i<n;i++){
 83                 if(In[i]==0&&Find(i)==i){
 84                     Q.push(i);
 85                 }
 86             }
 87             while(!Q.empty()){
 88                 //如果同一层有多个点,说明存在多个拓扑排序
 89                 if(Q.size()>1){
 90                     flag=false;
 91                 }
 92                 num--;
 93                 int u=Q.front();
 94                 Q.pop();
 95                 for(int i=0;i<vet[u].size();i++){
 96                     //只有入度为1的才可入队列
 97                     if(--In[vet[u][i]]==0){
 98                         Q.push(vet[u][i]);
 99                     }
100                 }
101             }
102             //说明存在环,矛盾
103             if(num>0){
104                 puts("CONFLICT");
105             }else if(!flag){
106                 puts("UNCERTAIN");
107             }else 
108                 puts("OK");
109         }
110     }
111     return 0;
112 }
原文地址:https://www.cnblogs.com/wally/p/3028532.html