P16467 [GKS 2013 Practice] Bad Horse 题解

很显然的一道并查集题目。

题目大意

给定 \(T\) 组测试用例,然后有 \(m\) 组麻烦成员对,麻烦成员对不能分到同一组,问能否将他们分成两组。

思路

对于每一个名字,我们用 map 数组来映射成数字编号。

首先初始化并查集数组,将 \(1\) 到 \(4m\) 的祖宗都设为自己。

然后对于每一组麻烦成员对,设他们的数字编号分别为 \(x\) 和 \(y\),那么我们将 \(x\) 和 \(y+2m\) 连边,将 \(x+2m\) 和 \(y\) 连边。

最后如果有任一人设为 \(x\),\(find(x)=find(x+2m)\),这说明这几组麻烦对里有环,也就是不能将他们划分为两组,不然就可以将他们分成两组。

参考代码

#include<bits/stdc++.h>
using namespace std;
const int N=105;
map<string,int> mp;//名字对应的数字编号
int fa[N*4];
int find(int x){
    return x==fa[x]?x:fa[x]=find(fa[x]);
}
void add(int x,int y){//连边
    int fx=find(x);
    int fy=find(y);
    fa[fy]=fa[fx];
}
int main(){
	std::ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    for(int id=1;id<=t;id++){
        mp.clear();//清空map
        int n;//这里将m写成n
        cin>>n;
        for(int i=1;i<=n*4;i++){
            fa[i]=i;//初始化并查集数组
        }
        int uns=0;//编号
        for(int i=1;i<=n;i++){
            string s1,s2;
            cin>>s1>>s2;
            int x=mp[s1],y=mp[s2];
            if(!x){//如果没出现过
                x=mp[s1]=++uns;
            }
            if(!y){//同上
                y=mp[s2]=++uns;
            }
            add(x,y+n*2);//连边
            add(x+n*2,y);
        }
        bool ans=0;
        for(int i=1;i<=uns;i++){//检查是否实现了环
            if(find(i)==find(i+n*2)){
                ans=1;break;//直接退出
            }
        }
        cout<<"Case #"<<id<<": ";//注意格式
        if(!ans){//可以
            cout<<"Yes\n";
        }else{//不可以
            cout<<"No\n";
        }
    }
	return 0;
}
/*

*/
posted @ 2026-10-17 21:05  SCX2014  阅读(2)  评论(0)    收藏  举报