描述
给出含n个点、m条边的无向图,结点编号为1..n。现在有4类操作:
1、Link u v:在结点 u 和 v 之间连一条无向边。
2、Query u v:查询 u 和 v 是否属于同一连通分量。
3、Count 询问当前图的连通分量数。
4、Max 询问当前最大的连同分量。
输入
第一行:三个整数n,m,n,m的意义如题目描述。 接下来m行:每行两个数u,v(1<=u,v<=n),表示结点u和v之间有条无向边。 接着的一行是一个整数q,表示操作数。 再接下来q行:每行是题目描述中的四种操作之一。
输出
输出每个查询的结果,对于Query u v 查询,如果u和v在同一连同分量中输出yEs,否则输出nO。
输入样例 1
8 4 8 2 3 7 1 5 6 3 14 Count Max Link 3 2 Count Max Query 1 2 Link 6 8 Query 2 6 Count Max Link 1 3 Query 5 7 Count Max
输出样例 1
4 3 3 5 nO yEs 3 5 yEs 2 7
提示
n<=200000m<=200000q<=200000
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,m; 4 const int maxn=0x3f3f3f; 5 int pa[maxn]; 6 int sz[maxn]; 7 int Max=0,cnt=0; 8 void makeset() 9 { 10 for(int i=1;i<=n;i++) 11 { 12 pa[i]=i; 13 sz[i]=1; 14 } 15 cnt=n; 16 Max=1; 17 } 18 int Find(int x) 19 { 20 int r=x; 21 while(pa[r]!=r) 22 r=pa[r]; 23 24 while(x!=r) 25 { 26 int y=pa[x]; 27 pa[x]=r; 28 x=y; 29 } 30 return r; 31 } 32 void Link(int x,int y) 33 { 34 int a=Find(x),b=Find(y); 35 if(a!=b) 36 { 37 pa[a]=b; 38 sz[b]+=sz[a]; 39 Max=max(Max,sz[b]); 40 cnt--; 41 } 42 } 43 bool Query(int x,int y) 44 { 45 return Find(x)==Find(y); 46 } 47 int main() 48 { 49 50 scanf("%d%d",&n,&m); 51 52 makeset(); 53 string s; 54 for(int i=1;i<=m;i++) 55 { 56 int x,y; 57 cin>>x>>y; 58 Link(x,y); 59 } 60 int t; 61 cin>>t; 62 while(t--) 63 { 64 cin>>s; 65 if(s=="Link") 66 { 67 int x,y; 68 scanf("%d%d",&x,&y); 69 Link(x,y); 70 } 71 if(s=="Query") 72 { 73 int x,y; 74 scanf("%d%d",&x,&y); 75 if(Query(x,y)==1) 76 printf("yEs\n"); 77 else 78 printf("nO\n"); 79 } 80 if(s=="Count") 81 { 82 printf("%d\n",cnt); 83 } 84 if(s=="Max") 85 { 86 printf("%d\n",Max); 87 } 88 } 89 return 0; 90 }