poj1703
题意:有两个帮派,给定一些操作,A a b判断a与b是否在同一帮派,D a b将a与b加入不同帮派
分析:非常好的并查集题目,用两倍的并查集分别来表示两个帮派,当进行D操作时,将a与b+n,a+n与b分别加同一帮派,A操作时进行判断,same(a,b)表示a与b在同一帮派,same(a,b+n)表示a与b在不同帮派,否则不能确定
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=100010; 15 int par[maxn*2],rankl[maxn*2]; 16 void init(int n){ 17 for(int i=0;i<n;i++){ 18 par[i]=i; 19 rankl[i]=0; 20 } 21 } 22 23 int findl(int x){ 24 if(par[x]==x) return x; 25 else{ 26 return par[x]=findl(par[x]); 27 } 28 } 29 30 void unite(int x,int y){ 31 x=findl(x); 32 y=findl(y); 33 if(x==y) return; 34 if(rankl[x]<rankl[y]){ 35 par[x]=y; 36 }else{ 37 par[y]=x; 38 if(rankl[x]==rankl[y]) rankl[x]++; 39 } 40 } 41 42 bool same(int x,int y ){ 43 return findl(x)==findl(y); 44 } 45 46 int main() 47 { 48 int t; 49 cin>>t; 50 while(t--) 51 { 52 int n,m; 53 cin>>n>>m; 54 init(n*2); 55 getchar(); 56 char s; 57 int a,b; 58 while(m--){ 59 scanf("%c%d%d%*c",&s,&a,&b); 60 if(s=='A'){ 61 if(same(a,b)){ 62 cout<<"In the same gang."<<endl; 63 } 64 else if(same(a,b+n)){ 65 cout<<"In different gangs."<<endl; 66 }else{ 67 cout<<"Not sure yet."<<endl; 68 } 69 }else{ 70 unite(a,b+n); 71 unite(a+n,b); 72 } 73 } 74 } 75 76 return 0; 77 }
AOJ2170
题意:给定一颗树,同时给出n个结点,以及每个结点的父结点,给出Q个操作,M a表示将a结点点亮,Q a表示找到与a相距最近的结点,问最后所有Q操作找到的结点之和
分析:用并查集维护,只不过结点变成了当前结点的父结点,注意会爆int
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=100010; 15 typedef struct p 16 { 17 int par,vis; 18 }p; 19 p s[maxn]; 20 21 void init(int n){ 22 for(int i=1;i<=n;i++){ 23 s[i].par=i; 24 s[i].vis=0; 25 } 26 } 27 int main() 28 { 29 int n,q; 30 while(cin>>n>>q) 31 { 32 if(n+q==0) break; 33 init(n); 34 s[1].vis=1; 35 for(int i=2;i<=n;i++){ 36 int x; 37 scanf("%d",&x); 38 s[i].par=x; 39 } 40 getchar(); 41 long long sum=0; 42 while(q--){ 43 char sh; 44 int a; 45 scanf("%c%d%*c",&sh,&a); 46 if(sh=='M'){ 47 s[a].vis=1; 48 }else{ 49 if(s[a].vis==1){ 50 sum+=a; 51 }else{ 52 while(true){ 53 if(s[a].vis==1){ 54 sum+=a; break; 55 }else{ 56 a=s[a].par; 57 } 58 } 59 } 60 } 61 } 62 cout<<sum<<endl; 63 } 64 return 0; 65 }