南昌大学航天杯第二届程序设计竞赛校赛网络同步赛 E

时间:2022-02-07 23:25:08

链接:https://www.nowcoder.com/acm/contest/122/E
来源:牛客网

题目描述

愉快的周末到了,小C和他的N-1个朋友买了M个游戏,游戏编号从1~M。每个游戏都是多人游戏,他们打算周末一起打游戏。

小C的每个朋友都决定好了要玩哪一款游戏(会有一组人打同一款游戏),并且每人手上都有一台游戏机,这种游戏机可以通过特定的游戏机连接线连接起来。

但是,他们面临着一个问题:目前没有一个朋友的游戏机是互相连接的。所以它们必须用可用的游戏机连接线连接起来。小C决定依次使用第 i 条连接线把他的朋友 ui 和 vi 的游戏机连接起来。也就是说,假设有Q条连接线,小C只能先使用第一条,然后使用第二条,然后使用第三条。。。最后使用第Q条。

一个游戏能开始的条件是所有玩这个游戏的朋友的游戏机都被连接起来(如果不是直接连接的话,那么就必须存在一条连接它们的路径)。他们希望尽快开始比赛。

在每个游戏中,找出在添加了第几条连接线之后能开始游戏。如果在一个游戏中只有一个人玩,则输出0(因为他立马可以开始游戏)。如果不存在,则输出-1

输入描述:

多组输入

第一行包含三个整数N,M,Q。

第二行给N个用空格分隔的整数,第 i 个整数代表第 i 个朋友想玩的游戏。

接下来的Q行,每行两个整数(u, v),代表电线 i 连接的两个人的电脑

1 <= N, M <= 10^5
0 <= Q <= 10^5

输出描述:

对于每个游戏,输出一个整数,表示添加了第几条连接线之后能开始游戏,每行以换行符结束
示例1

输入

5 2 4
1 2 2 2 1
1 2 
2 3
1 5
4 5

输出

3
4

说明

**样例解释**

第一个游戏有两个人参加(1,5),在添加了第三条电线之后他们电脑互相连接

第二个游戏三个人参加(2, 3, 4),在添加第四条电线之后他们电脑互相连接
#include<bits/stdc++.h>
 
using namespace std;
const int maxn = 1e5+55;
int cnt[maxn],x,n,m,q;
int f[maxn];
map<int,int> mp[maxn];
int res[maxn];
int find(int x){
    if(x == f[x]) return x;
    return f[x] = find(f[x]);
}
int main () {
    while(~scanf("%d%d%d",&n,&m,&q)) {
        memset(cnt,0,sizeof cnt);
        memset(res,-1,sizeof res);
        for(int i=1;i<=n;i++)
            mp[i].clear();
        for(int i=1;i<=n;i++){
            scanf("%d",&x);
            cnt[x]++;
            mp[i][x]++;
        }
        for(int i=1;i<=n;i++)
            f[i]=i;
        for(int i=1;i<=q;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            int h1 = find(u);
            int h2 = find(v);
            if(h1 == h2) continue;
            if(mp[h1].size() > mp[h2].size()){
                for(auto ep:mp[h2]) {
                    int tmp = (mp[h1][ep.first] += ep.second);
                    if(tmp == cnt[ep.first]) {
                        res[ep.first]=i;
                        mp[h1].erase(ep.first);
                    }
                }
                f[h2]=h1;
            } else {
                for(auto ep:mp[h1]) {
                    int tmp = (mp[h2][ep.first] += ep.second);
                    if(tmp == cnt[ep.first]) {
                        res[ep.first]=i;
                        mp[h2].erase(ep.first);
                    }
                }
                f[h1]=h2;
            }
        }
        for(int i=1;i<=m;i++){
            if(cnt[i]==1){
                printf("0\n");
            } else {
                printf("%d\n",res[i]);
            }
        }
    }
    return 0;
}