http://poj.org/problem?id=1182
维护每个孩子和父亲的关系,0=和父亲同类,1=可以吃父亲,2=可以被父亲吃.
整个题,只有一个主要集合,这个和其他并查集不一样有很多大小不同的集合,然后合并,这个题目是每次将一个未知的点插入到已知关系的集合中,并建立与父亲的关系,然后每次查找的路径压缩让两个节点可以通过父亲来判断他们的关系,比如 v[x]=1 v[y]=2 说明x吃了他父亲,y能被他父亲吃,所以y可以吃掉x,这样就能找到关系了,路径压缩的时候 要理解好递归的思路,每次通过自己的父亲算出与上一个父亲的关系,自己画一画然后思考.这次比较幸运,竟然能够一次AC,说明我的编码能力有提高. 说真的,结构体类,真的挺好玩的...构造函数可以写struct...
code:
1 #include<iostream>
2 #include<cstdio>
3 using namespace std;
4 #define REP(i,from,to) for(int i=(from);i<=(to);++i)
5 int a[50001];
6 int v[50001];
7 int n;
8 struct disset{
9 int *d;
10 int *v;
11 int l;
12 disset(int *_d,int *_v,int _l):d(_d),v(_v),l(_l){
13 REP(i,1,l){
14 a[i]=i;
15 v[i]=0;
16 }
17 }
18 int find(int x){
19 int u = d[x];
20 if(u!=x){
21 d[x] = find(u);
22 v[x] = (v[x]+v[u]) % 3;
23 }
24 return d[x];
25 }
26 void same(int x,int y){
27 int u = find(x);
28 d[u] = y;
29 if(v[x]==0)
30 v[u]=0;
31 else if(v[x]==1)
32 v[u]=2;
33 else
34 v[u]=1;
35
36 }
37 void eat(int x,int y){
38 int u = find(x);
39 d[u]=y;
40 if(v[x]==2)
41 v[u]=2;
42 else if(v[x]==0)
43 v[u]=1;
44 else
45 v[u]=0;
46 }
47 bool is_eat(int x,int y){
48 if(v[x]==0 && v[y]==2 ||
49 v[x]==1 && v[y]==0 ||
50 v[x]==2 && v[y]==1)
51 return true;
52 return false;
53 }
54 };
55 struct disset *s;
56 bool sentence(int d,int x,int y){
57 if(x>n || y>n)
58 return false;
59 if(d==1){
60 int ux = s->find(x);
61 int uy = s->find(y);
62 if(ux!=uy){
63 s->same(x,y);
64 }
65 else if(v[x]!=v[y])
66 return false;
67 }
68 else{
69 int ux = s->find(x);
70 int uy = s->find(y);
71 if(ux!=uy){
72 s->eat(x,y);
73 }
74 else if(!s->is_eat(x,y))
75 return false;
76 }
77 return true;
78 }
79 int main(){
80 int ccase,ans=0;
81 scanf("%d%d",&n,&ccase);
82 //REP(i,1,5)
83 // cout<<i<<" |";
84 //cout<<endl;
85 s = new struct disset(a,v,n);
86 while(ccase--){
87 int d,x,y;
88 scanf("%d%d%d",&d,&x,&y);
89 if(!sentence(d,x,y))
90 ans++;
91
92 // REP(i,1,5)
93 // cout<<a[i]<<' '<<v[i]<<'|';
94 // cout<<endl;
95 }
96 printf("%d\n",ans);
97 return 0;
98 }
posted on 2012-07-08 23:15
Gin 阅读(351)
评论(0) 编辑 收藏 引用 所属分类:
Data Structure