NC15976 小C的周末

题目链接

题目链接

题意

愉快的周末到了,小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;
            }
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hlee-top

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值