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!
原文地址:https://www.cnblogs.com/sytu/p/3868754.html