ACM1811拓扑排序和并查集
1 /* 2 ACM1811 可以利用拓扑排序和并查集解决,主要方式是利用并查集在输入数据的时候将所有相等的点合并 3 然后将处理完的数据统一按照一个符号方向连接成有向线段,利用的是邻接矩阵;接下来把每条边都进行履历 4 如果出现conflict,那么就会在去除所有入度的时候无法找到新的零入度点,那么就会似的point无法减到零, 5 表示有conflict,如果出现uncertain,那么就会在一次寻找新的零入度点时能找到多个点,导致在队列中保存 6 多个数据 ; 7 */ 8 #include<iostream> 9 #include<queue> 10 using namespace std; 11 class EDGE 12 { 13 public: 14 int from,to; 15 char sign; 16 }; 17 class WAY 18 { 19 public: 20 int from,to,next; 21 }; 22 class DEAL 23 { 24 public: 25 DEAL(int n,int m) 26 { 27 edge=new EDGE[m]; 28 way=new WAY[m]; 29 father=new int[n]; 30 head=new int[n]; 31 into=new int[n]; 32 for(int i=0;i<n;i++) 33 { 34 father[i]=i;head[i]=-1; 35 into[i]=0; 36 } 37 number=n; 38 point=n; 39 side=m; 40 count=0; 41 certain=true; 42 conflict=false; 43 } 44 ~DEAL() 45 { 46 delete []edge; 47 delete []father; 48 delete []way; 49 delete []head; 50 delete []into; 51 } 52 void Input() 53 { 54 for(int i=0;i<side;i++) 55 { 56 cin>>edge[i].from>>edge[i].sign>>edge[i].to; 57 if(edge[i].sign=='=') 58 { 59 int fa=FindFather(edge[i].from); 60 int fb=FindFather(edge[i].to); 61 Union(fa,fb); 62 point--; 63 } 64 } 65 } 66 void Preprocess() 67 { 68 for(int i=0;i<side;i++) 69 { 70 if(edge[i].sign=='=')continue; 71 int fa=FindFather(edge[i].from); 72 int fb=FindFather(edge[i].to); 73 if(fa==fb)conflict=true; 74 if(edge[i].sign=='<') 75 Merge(fb,fa); 76 else if(edge[i].sign=='>') 77 Merge(fa,fb); 78 } 79 } 80 void Toposort() 81 { 82 for(int i=0;i<number;i++) 83 { 84 if(into[i]==0&&father[i]==i)//是头节点 85 q.push(i); 86 } 87 while(!q.empty()) 88 { 89 int l=q.front(); 90 q.pop(); 91 point--; 92 if(!q.empty())certain=false; 93 int v; 94 for(v=head[l];v!=-1;v=way[v].next) 95 { 96 int u=way[v].to; 97 into[u]--; 98 if(!into[u])q.push(u); 99 } 100 } 101 } 102 void Output() 103 { 104 if(point>0||conflict) 105 cout<<"CONFLICT"<<endl; 106 else if(!certain)cout<<"UNCERTAIN"<<endl; 107 else cout<<"OK"<<endl; 108 } 109 int FindFather(int x) 110 { 111 if(x==father[x])return x; 112 return father[x]=FindFather(father[x]); 113 } 114 void Union(int x,int y) 115 { 116 if(x!=y)father[y]=x;//后面跟着前面 117 } 118 void Merge(int x,int y) 119 { 120 way[count].from=x; 121 way[count].to=y; 122 way[count].next=head[x]; 123 into[y]++; 124 head[x]=count++; 125 } 126 private: 127 queue<int>q; 128 int number,side,point,count; 129 EDGE *edge; 130 WAY *way; 131 int *father,*head,*into; 132 bool certain,conflict; 133 }; 134 int n,m; 135 int main() 136 { 137 while(cin>>n>>m) 138 { 139 DEAL ob(n,m); 140 ob.Input(); 141 ob.Preprocess(); 142 ob.Toposort(); 143 ob.Output(); 144 } 145 return 0; 146 }
What I don't dare to say is I can't!