食物链(并查集问题)pku1182

http://acm.pku.edu.cn/JudgeOnline/problem?id=1182
#include <stdio.h> #define max 50000+5 int f[max]; int r[max]; /* rank[x]表示father[x]与x的关系 rank[x] == 0 表示father[x]与x是同类 rank[x] == 1 表示x吃father[x] rank[x] == 2 表示father[x]吃x */ void make_set(int x) { f[x]=x; r[x]=0; } int find_set(int x) { if (f[x]==x) return x; int t=f[x]; f[x]=find_set(t); r[x]=(r[t]+r[x])%3; //important. 更新r[]数组中x与代表元素的相对关系。更新原因: //代表元素在union_set操作中被改变了。 //至于这个式子的推得.可以枚举rx与p[x], p[x]与x的关系,然后观察得到。 //更好的方法是向量运算。 return f[x]; } void union_set(int x,int y,int d) { int a=find_set(x); int b=find_set(y); f[a]=b; r[a] = (r[y] - r[x]+ 2 + d ) % 3; //同上。这两个关系的推得实际上是这道题的关键所在。 } int main() { int n,k; int d,x,y,lie=0; scanf("%d%d",&n,&k); for (int i=0;i<max;i++) make_set(i); while (k--) { int a,b; scanf("%d%d%d",&d,&x,&y); if (d==2&&x==y) {lie++;continue;} if (x>n||y>n) {lie++;continue;} a=find_set(x); b=find_set(y); if (a==b) { if (d==1&&r[x]!=r[y]) lie++; else { if (d==2&&r[x]!=(r[y]+1)%3) lie++; } } else union_set(x,y,d); } printf("%d/n",lie); return 0; }

 

 

Sample Input

100 7

1 101 1

2 1 2

2 2 3

2 3 3

1 1 3

2 3 1

1 5 5

Sample Output

3

 

我在这里演示下这个例子

n=100;k=7;

lie=0;

>>d     x   y

>>1     101 1   x>n lie++;

>>2     1   2   f[1]==1与f[2]==2都是指向自己,接着union_set(1,2,2)将1,2合并

            我们进入union_set看看,f[1]=2;r[1]=(r[2]-r[1]+2+2)%3=(0-0+4)%3=1,

            即r[1]=1,1吃2(f[1])

>>2 2   3   同上,得到f[2]=3,r[2]=(r[3]-r[2]+2+2)%3=1,2吃3(f[2])

            f[3]=3,r[3]=0

>>2 3   3   d==2,x==1,y==3 lie++

>>1 1   3   d=1,x=1,y=3;

            我们进入find_set看看,find_set(1) {f[1]==2!=1,t=2,f[1]=find_set(t)

            {f[2]==3!=2,t=3,f[2]=find_set(t){f[3]==3,return f[3]即3},f[2]=3

            r[2]=(r[t]+r[2])%3=1,return f[2]即3},f[1]=3,r[1]=(r[t]+r[1])%3=             2,return 3(f[1]).即f[1]=3,r[1]=2

            d==1,r[1]==2,r[3]==0;r[1]!=r[3]即1与3对各自的上节点不具有相同行为

            所以1与3不属于同类 lie++

>>2 3   1   d==2,x==3,y==1

            f[3]==3而f[1]==3,所以可以进行真假话的判断

            d==2,r[3]==0,r[1]==2;r[3]==(r[1]+1)%3(即3吃1)

>>1 5   5   d==1,x==5,y==5

            f[x]==5,f[y]==5,可以进行真假话的判断

            d==1,r[x]==5,r[y]==5

你可能感兴趣的:(input,output)