5月12日

poj1182

题意:http://poj.org/problem?id=1182

分析:并查集的经典题目,在这题当中,我们不仅要用并查集维护属于同一类,同时还应该用并查集维护被吃的关系。因为物种属于A,B,C三种,所以我们开一个n*3来进行纪录。然后如果是1的话,那分别合并到三个集合,如果是2的话,按照食物链的关系进行合并。注意在合并之前我们需要进行判断,如果是1的话,要判断该元素是否在另外两类中出现过,如果是2的话,要判断食物链是否有矛盾。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <string>
 5 #include <vector>
 6 #include <algorithm>
 7 #include <set>
 8 #include <map>
 9 #include <bitset>
10 #include <cmath>
11 #include <queue>
12 #include <stack>
13 using namespace std;
14 const int maxn=50002;
15 int par[maxn*3],rankl[maxn*3];
16 
17 //并查集模板
18 void init(int n){
19     for(int i=0;i<n;i++){    //初始化
20         par[i]=i;
21         rankl[i]=0;
22     }
23 }
24 
25 int findl(int x){   //查找跟结点
26     if(x==par[x]){
27         return x;
28     }else{
29         return par[x]=findl(par[x]);
30     }
31 }
32 
33 void unite(int x,int y){   //合并操作
34     x=findl(x);
35     y=findl(y);
36     if(x==y) return;
37     if(rankl[x]<rankl[y]){
38         par[x]=y;
39     }else{
40         par[y]=x;
41         if(rankl[x]==rankl[y])   rankl[x]++;
42     }
43 }
44 
45 bool same(int x,int y){   //判断是否在同一集合
46     return findl(x)==findl(y);
47 }
48 
49 int main()
50 {
51     int n,k;
52     cin>>n>>k;
53     init(n*3);
54     int cnt=0;
55     for(int i=0;i<k;i++){
56         int id,x,y;
57         scanf("%d%d%d",&id,&x,&y);
58         --x,--y;
59         if(x<0||y<0||n<=x||n<=y){
60             cnt++; continue;
61         }
62         if(id==1){
63             if(same(x,y+n)||same(x,y+2*n)){
64                 cnt++;
65             }else{
66                 unite(x,y);
67                 unite(x+n,y+n);
68                 unite(x+2*n,y+2*n);
69             }
70         }else{
71             if(same(x,y)||same(x,y+2*n)){
72                 cnt++;
73             }else{
74                 unite(x,y+n);
75                 unite(x+n,y+2*n);
76                 unite(x+2*n,y);
77             }
78         }
79     }
80     cout<<cnt<<endl;
81     return 0;
82 }
View Code

 

poj2236

题意:因为地震,使网络不能联通,经过维修之后可以连通不超过距离d的网络,任何网络可以作为其他两个网络的中介。O表示维修,S表示是否连通

分析:裸的并查集,O的时候把符合要求的并入集合,S的时候看是否属于同一个集合即可。注意不行的时候是FAIL,2333

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <string>
 5 #include <vector>
 6 #include <algorithm>
 7 #include <set>
 8 #include <map>
 9 #include <bitset>
10 #include <cmath>
11 #include <queue>
12 #include <stack>
13 using namespace std;
14 const int maxn=1010;
15 int par[maxn],rankl[maxn];
16 
17 void init(int n){
18     for(int i=0;i<=n;i++){
19         par[i]=i;
20         rankl[i]=0;
21     }
22 }
23 
24 int findl(int x){
25     if(x==par[x])
26         return x;
27     else{
28         return par[x]=findl(par[x]);
29     }
30 }
31 
32 void unite(int x,int y){
33     x=findl(x);
34     y=findl(y);
35     if(x==y)  return;
36     if(rankl[x]<rankl[y]){
37         par[x]=y;
38     }else{
39         par[y]=x;
40         if(rankl[x]==rankl[y])  rankl[x]++;
41     }
42 }
43 
44 bool same(int x,int y){
45     return findl(x)==findl(y);
46 }
47 
48 int n,d;
49 bool judge(int x1,int y1,int x2,int y2){
50     if((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)>d*d)
51         return false;
52     else return true;
53 }
54 
55 struct p{
56     int id,x,y,vis;
57 }s[maxn];
58 int main()
59 {
60     cin>>n>>d;
61     init(n);
62     for(int i=1;i<=n;i++){
63         cin>>s[i].x>>s[i].y;
64         s[i].id=i;
65         s[i].vis=0;
66     }
67     char ch[5];
68     while(scanf("%s",ch)!=EOF){
69         int a,b;
70         if(ch[0]=='O'){
71             cin>>a;
72             s[a].vis=1;
73             for(int i=1;i<=n;i++){
74                 if(judge(s[i].x,s[i].y,s[a].x,s[a].y)&&s[i].vis&&i!=a)
75                     unite(i,a);
76             }
77         }else if(ch[0]=='S'){
78             cin>>a>>b;
79             if(same(a,b))
80                 cout<<"SUCCESS"<<endl;
81             else
82                 cout<<"FAIL"<<endl;
83         }
84     }
85     return 0;
86 }
View Code

 

posted @ 2016-05-12 22:42  wolf940509  阅读(185)  评论(0编辑  收藏  举报