链接:
https://www.nowcoder.com/acm/contest/50/G
来源:牛客网
来源:牛客网
题目描述
幼儿园的孩子们正在做游戏,每个人都有自己的帮派,帮派之间打架,然后赢者吞并弱者扩大自己的势力。最开始每个孩子的帮派中只有自己,然后接下来有会有两个人打架,这两个人会集结自己所属的势力开始打架,打赢的一方就会吞并输的一方,当然如果x,y是一个势力就不会打起来。有些聪明的小朋友会将自己的糖分给其他小朋友引诱他离开所属势力加入到自己势力。又有一些小朋友会对现在的势力不满,然后反叛出去自立门户。
作为打架的双方,只有人数大于另一方才能打赢。即:人数相等则没有输赢,两个帮派没有变化。
幼儿园里面共有N个孩子,接下来有M次操作,操作有如下4种
1) query 查询现在有多少个势力。
2) fight x y 表示x,y打架.并输出"z is winner!"胜利的一方(z是x或y),如果没有打平则输出"Either is winner!".如果x,y属于同一个势力不会打架,当然也不用输出.
3) tempt x y 表示x诱惑y、将y拉入x的势力。
4) revolt x 表示x反叛,(自立门户)
输入描述:
第一行输入一个T代表有T组数据 接下来第一行有两个整数N,M,代表N个孩子,M次操作。 接下来有M行。每行输入有如下三种。 1) query 2) fight x y 3) tempt x y 4) revolt x 1<=T<=10; 1<=N,M<=100000; 1<=x,y<=N;
#include<bits/stdc++.h>
using namespace std;
const int maxn=200007;
int par[maxn],ran[maxn],id[maxn],ans;
void init()
{
for(int i=0;i<maxn;i++)
par[i]=i,ran[i]=1,id[i]=i;
}
int find(int x)
{
if(x==par[x])return x;
return par[x]=find(par[x]);
}
void unite(int x,int y)
{
x=find(x);y=find(y);
if(x!=y)
{
par[x]=y;
ran[y]+=ran[x];
ran[x]=0;
}
}
int main()
{
int T,cas=0;scanf("%d",&T);
while(T--)
{
printf("Case #%d:\n",++cas);
int n,m,cnt;scanf("%d%d",&n,&m);
init();
cnt=ans=n;
cnt++;
while(m--)
{
char t[10];int x,y;
scanf("%s",&t);
if(t[0]=='q') printf("%d\n",ans);
else if(t[0]=='f')
{
int x,y;scanf("%d%d",&x,&y);
int x1=find(id[x]),y1=find(id[y]);
if(x1==y1)continue;
if(ran[x1]>ran[y1])
{
printf("%d is winner!\n",x);
unite(x1,y1);
ans--;
}
else if(ran[x1]<ran[y1])
{
printf("%d is winner!\n",y);
unite(x1,y1);
ans--;
}
else printf("Either is winner!\n");
}
else if(t[0]=='t')
{
int x,y;scanf("%d%d",&x,&y);
x=find(id[x]);
int y1=find(id[y]);
if(ran[y1]==1)ans--;
ran[y1]--;
id[y]=cnt++;
unite(x,id[y]);
}
else if(t[0]=='r')
{
int x;scanf("%d",&x);
int x1=find(id[x]);
if(ran[x1]>1)id[x]=cnt++,ran[x1]--,ans++;
}
}
}
return 0;
}