题目大意

今天,小 ​​x​​ 因为太无聊,就在玩游戏。

这个游戏有两个队伍,然后他们在游戏里面打来打去。

但小 ​​x​​ 遇到了难题。他不知道自己的队友是谁。他只知道总共有两个队伍,每队有 \(n\) 个人和很多组击杀情况。

他想问你,现在他能否知道两个队伍分别有谁。

你可以帮助小 ​​x​​ 吗?

解题思路

并查集水题。

对名字进行哈希,或者用 ​​map​​。

设 \(x+2*n\) 为 \(x\) 的敌人,

则 \(x\) 和 \(y\) 是敌人,即表示为 \(fa[find(a + 2 * n)] = find(b),fa[find(b + 2 * n)] = find(a)\),因为敌人的敌人是朋友嘛。

最后判断是否有矛盾即可。

考场判断写错,惨丢 \(30pts\),啊!

AC CODE
#include <bits/stdc++.h>
using namespace std;

#define int long long

const int _ = 200007;

const int base = 233;

const int mod = 1e9 + 7;

int T, n, m;

int fa[_];

int k, f[_];

map<long long, int> q;

int sm[_];

void init()
{
for(int i = 1; i <= k; ++i) q[f[i]] = 0;
k = 0;
memset(sm, 0, sizeof sm);
for(int i = 1; i < _; ++i) fa[i] = i;
}

int find(int x)
{
return fa[x] == x ? x : fa[x] = find(fa[x]);
}

char c[15];

signed main()
{
// freopen("game.in", "r", stdin);
// freopen("game.out", "w", stdout);
scanf("%lld", &T);
while(T--)
{
int ans = 0;
scanf("%lld%lld", &n, &m);
init();
for(int i = 1; i <= m; ++i)
{
scanf("%s", c);
int a, b;
int x = 0;
for(int j = 0, len = strlen(c); j < len; ++j)
{
x = (x * base % mod + (int)(c[j] - 'a' + 1)) % mod;
}
if(!q[x])
{
q[x] = ++k;
f[k] = x;
a = k;
}
else
{
a = q[x];
}
scanf("%s", c);
x = 0;
for(int j = 0, len = strlen(c); j < len; ++j)
{
x = (x * base % mod + (int)(c[j] - 'a' + 1)) % mod;
}
if(!q[x])
{
q[x] = ++k;
f[k] = x;
b = k;
}
else
{
b = q[x];
}
fa[find(a + 2 * n)] = find(b);
fa[find(b + 2 * n)] = find(a);

}
if(2 * n > k)
{
puts("NO");
continue;
}
for(int i = 1; i <= n * 2; ++i)
sm[find(i)]++;
bool flag = 0;
for(int i = 1; i <= n * 2; ++i)
{
if(sm[i] == n)
{
printf("YES\n");
flag = 1;
break;
}
}
if(!flag) printf("NO\n");
}
}