hdu 1811 Rank of Tetris(拓扑,并查集)

题意:略

分析:排序先按rating,若相同,则按rp。考虑到每个人的rp均不同,所以rating相同的人必然可以排序。那么只需要考虑rating不同的集合了。

    大小关系可以用有向边表示,而大小关系的传递可以用拓扑排序来呈现。

    接着就要分析,三种结果对应的情况了。

    很明显,ok要求拓扑出来的必须是一条链,一旦有分支,分支处的两个(或多个)点的大小关系就不明确,也就是条件不足=>uncertain。

    而矛盾conflict有两种情况:1、更改关系0=1,0>1;2、自相矛盾,即成环,0>1,0<1。

注意:在条件不足和矛盾同时发生时,要求输出的是矛盾conflict。

    这里要注意,拓扑排序是可以判环的:只要完成拓扑后,发现还有点没有加入队列,那么就说明他们之间成环。若不成环,必然可以把所有点加入队列。

    学习了vector的find函数

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<vector>
  4 #include<queue>
  5 #include<algorithm>
  6 using namespace std;
  7 
  8 const int MAXN=11111;
  9 
 10 struct Edge{
 11     int x,y;
 12     char op;
 13 }edge[MAXN<<1];
 14 
 15 vector<int>G[MAXN];
 16 queue<int>q;
 17 int in[MAXN],f[MAXN];
 18 int inq[MAXN];
 19 
 20 void init(int n)
 21 {
 22     for(int i=0;i<n;i++)
 23         f[i]=i;
 24 
 25     memset(in,0,sizeof(in));
 26 
 27     for(int i=0;i<n;i++)
 28         G[i].clear();
 29 }
 30 
 31 int Find(int x)
 32 {
 33     return f[x]==x?x:f[x]=Find(f[x]);
 34 }
 35 
 36 int top(int n)
 37 {
 38     int flog=1;
 39     while(!q.empty())
 40         q.pop();
 41     memset(inq,0,sizeof(inq));//判入队
 42 
 43     for(int i=0;i<n;i++)
 44     {
 45         int x=Find(i);
 46         if(x!=i)//忽略所有集合中除根以外的点
 47             inq[i]=1;
 48         else if(in[x]==0){
 49             q.push(x);
 50             inq[x]=1;
 51         }
 52     }
 53     if(q.empty())//队空,成环,冲突
 54         return -1;
 55     while(!q.empty())
 56     {
 57         if(q.size()>=2)//多叉,不分先后,条件不足
 58             flog=0;
 59 
 60         int u=q.front();q.pop();
 61         int sz=G[u].size();
 62         for(int i=0;i<sz;i++)
 63         {
 64             int v=G[u][i];
 65             in[v]--;
 66             if(in[v]==0){
 67                 if(inq[v])//成环,冲突
 68                     return -1;
 69                 else {
 70                     q.push(v);
 71                     inq[v]=1;
 72                 }
 73             }
 74         }
 75     }
 76     for(int i=0;i<n;i++)
 77         if(!inq[i])//不能全部拓扑,成环,冲突
 78             return -1;
 79     return flog;
 80 }
 81 
 82 int main()
 83 {
 84     int n,m;
 85     while(~scanf("%d%d",&n,&m))
 86     {
 87         int flog=1;
 88         init(n);
 89         for(int i=0;i<m;i++)
 90         {
 91             scanf("%d %c %d",&edge[i].x,&edge[i].op,&edge[i].y);
 92             if(edge[i].op=='='){
 93                 int a=Find(edge[i].x);
 94                 int b=Find(edge[i].y);
 95                 f[a]=b;
 96             }
 97         }
 98         for(int i=0;i<m;i++)
 99         {
100             if(edge[i].op=='=')
101                 continue;
102 
103             int a=Find(edge[i].x);//所有处理都是对集合的根做操作
104             int b=Find(edge[i].y);
105             if(a==b)
106                 flog=-1;
107             if(flog==-1)
108                 break;
109 
110             if(edge[i].op=='<'){
111                 if(find(G[b].begin(),G[b].end(),a)==G[b].end()){//去重,长知识了
112                     G[b].push_back(a);
113                     in[a]++;
114                 }
115             }else{
116                 if(find(G[a].begin(),G[a].end(),b)==G[a].end()){
117                     G[a].push_back(b);
118                     in[b]++;
119                 }
120             }
121         }
122         if(flog==-1){
123             printf("CONFLICT\n");
124             continue;
125         }
126         flog=top(n);
127         if(flog==-1)
128             printf("CONFLICT\n");
129         else if(flog==0)
130             printf("UNCERTAIN\n");
131         else
132             printf("OK\n");
133     }
134     return 0;
135 }
136 /*
137 4 3
138 0 < 1
139 1 < 2
140 2 < 0
141 
142 4 3
143 0 > 1
144 1 < 2
145 0 > 2
146 
147 4 3
148 1 = 2
149 0 < 1
150 3 > 2
151 
152 4 3
153 1 = 2
154 0 < 1
155 0 > 2
156 
157 3 3
158 1 = 2
159 2 = 0
160 1 > 2
161 
162 3 1
163 1 < 2
164 */
View Code

posted @ 2013-10-19 16:26  Thousand Sunny  阅读(207)  评论(0编辑  收藏  举报