题目链接
题意
愉快的周末到了,小C和他的N-1个朋友买了M个游戏,游戏编号从1~M。每个游戏都是多人游戏,他们打算周末一起打游戏。
小C的每个朋友都决定好了要玩哪一款游戏(会有一组人打同一款游戏),并且每人手上都有一台游戏机,这种游戏机可以通过特定的游戏机连接线连接起来。
但是,他们面临着一个问题:目前没有一个朋友的游戏机是互相连接的。所以它们必须用可用的游戏机连接线连接起来。小C决定依次使用第 i 条连接线把他的朋友 ui 和 vi 的游戏机连接起来。也就是说,假设有Q条连接线,小C只能先使用第一条,然后使用第二条,然后使用第三条。。。最后使用第Q条。
一个游戏能开始的条件是所有玩这个游戏的朋友的游戏机都被连接起来(如果不是直接连接的话,那么就必须存在一条连接它们的路径)。他们希望尽快开始比赛。
在每个游戏中,找出在添加了第几条连接线之后能开始游戏。如果在一个游戏中只有一个人玩,则输出0(因为他立马可以开始游戏)。如果不存在,则输出-1
思路
- 并查集,用map[x][y]表示x玩家所在的集合玩y游戏的人数
- 若人数等于num[y]则为该游戏的答案
参考代码
#include<bits/stdc++.h>
using namespace std;
int num[100010];
int fa[100010];
int ans[100010];
map<int,int> aa [100010];
int find1(int x)
{
if(fa[x]==x)
return x;
fa[x]=find1(fa[x]);
return fa[x];
}
int main()
{
int n,m,q;
while(cin>>n>>m>>q)
{
memset(num,0,sizeof(num));
memset(ans,-1,sizeof(ans));
for (int i = 1; i <= n; ++i)
aa[i].clear();
int tmp;
for(int i=1; i<=n; i++)
{
cin>>tmp;
aa[i][tmp]++;
num[tmp]++;
fa[i]=i;
}
int u,v;
for(int i=1; i<=q; i++)
{
cin>>u>>v;
u=find1(u);
v=find1(v);
if(aa[u].size()<aa[v].size())
swap(u,v);
fa[v]=u;
map<int,int>::iterator it;
for(it =aa[v].begin(); it!=aa[v].end(); it++)
{
aa[u][it->first]+=it->second;
if(aa[u][it->first]==num[it->first])
{
ans[it->first]=i;
}
}
aa[v].clear();
}
for(int i=1; i<=m; i++)
{
if(num[i]==1)
{
cout<<0<<endl;
}
else
{
cout<<ans[i]<<endl;
}
}
}
}