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

来源:互联网 发布:安卓数据库 编辑:程序博客网 时间:2024/05/18 12:41

题目链接: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 }

 

0 0