Rank of Tetris HDU - 1811

原题链接

考察:并查集+拓扑序列+离线处理

难点在于并查集如何运用,我是卡在如何判断条件不足那里卡了很久.拓扑序列处理不了等号问题.如果用队列中无根结点的元素>2来判断条件不足的话,也存在相等利用序号大小排列名次的问题.因此这题就没写出来...

错误思路1:

        利用并查集判矛盾,利用拓扑序列判断是否无法判断.这个思路是参考直接的食物链设置距离数组.但是这道题a>b,b>c说明a>c这个在并查集里会判断a=c,因此这道题的距离并不是3个一循环所以错误

正确思路 :

        很容易想到成环判断是否矛盾,条件不足的情况就是无根节点是否有1个以上

        需要处理的就是无根结点到底有没有等号关系,暴力枚举一定TLE.但是这道题相等具有传递性,因此可以用并查集维护.

易错:

         必须先将等号关系的元素先加到集合里,再将所有相等的元素的邻接表元素全部接到根节点.

  1. 加入等号关系意味着拓扑序列的元素减少,必须判重避免多减
  2. 用SET的pair判重会WA...原因是当已经并在集合里的元素set会多算一次
 1 #include <iostream>
 2 #include <queue>
 3 #include <algorithm>
 4 using namespace std;
 5 const int N = 1e5+10;
 6 const int M = 2e5+10;
 7 int h[N],e[M],ne[M],d[M],p[N],idx,m,n,sum;
 8 int l[M],r[M];
 9 char op[M];
10 void add(int a,int b)
11 {
12     e[idx]=b,ne[idx]=h[a],h[a]=idx++;
13 }
14 int findf(int x)
15 {
16     if(x!=p[x]) p[x] = findf(p[x]);
17     return p[x];
18 }
19 void inits()
20 {
21     fill(d,d+M,0); fill(h,h+N,-1);
22     idx = 0; sum = 0;
23     for(int i=0;i<n;i++) p[i]=i;
24 }
25 int merge(int a,int b)
26 {
27     int x=findf(a);
28     int y=findf(b);
29     if(x==y) return 0;//set去重的错误原因 
30     p[x] = y;
31     return 1;
32 }
33 void topsort()
34 {
35     queue<int> q;
36     bool unsure = false;
37     for(int i=0;i<n;i++) if(!d[i]&&findf(i)==i) q.push(i);//我真的好菜... 
38     while(!q.empty())
39     {
40         int sz = q.size();
41         if(sz>1) unsure = 1;
42         sum+=sz;
43         while(sz--)
44         {
45             int x = q.front();
46             q.pop();
47             for(int i=h[x];i!=-1;i=ne[i])
48             {
49                 int j = e[i]; d[j]--;
50                 if(!d[j]) q.push(j);
51             }
52         }
53     }
54     if(sum!=n) printf("CONFLICT\n");
55     else if(unsure) printf("UNCERTAIN\n");
56     else printf("OK\n");
57 }
58 int main()
59 {
60 //    freopen("in.txt","r",stdin);
61     while(scanf("%d%d",&n,&m)!=EOF)
62     {
63         inits();
64         for(int i=0;i<m;i++)
65         {
66             scanf("%d %c %d",&l[i],&op[i],&r[i]);
67             if(op[i]=='=')
68                 if(merge(l[i],r[i])) sum++; 
69         }
70         for(int i=0;i<m;i++)
71         {
72             int px = findf(l[i]); int py = findf(r[i]);
73             if(op[i]=='<') { add(py,px); d[px]++;}
74             else if(op[i]=='>') { add(px,py); d[py]++;}
75         }
76         topsort();
77     }
78     return 0;
79 }

 

        

 

posted @ 2021-01-11 14:42  acmloser  阅读(61)  评论(0编辑  收藏  举报