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;
}
/*
*/

浙公网安备 33010602011771号