题目大意
今天,小 x
因为太无聊,就在玩游戏。
这个游戏有两个队伍,然后他们在游戏里面打来打去。
但小 x
遇到了难题。他不知道自己的队友是谁。他只知道总共有两个队伍,每队有
n
n
n 个人和很多组击杀情况。
他想问你,现在他能否知道两个队伍分别有谁。
你可以帮助小 x
吗?
对于 100 % 100\% 100% 的数据, t < = 10 , n < = 2000 , m < = 100000 t<=10,n<=2000,m<=100000 t<=10,n<=2000,m<=100000。
数据保证不会有矛盾的关系。
解题思路
并查集水题。
对名字进行哈希,或者用 map
。
设 x + 2 ∗ n x+2*n x+2∗n 为 x x x 的敌人,
则 x x x 和 y y y 是敌人,即表示为 f a [ f i n d ( a + 2 ∗ n ) ] = f i n d ( b ) , f a [ f i n d ( b + 2 ∗ n ) ] = f i n d ( a ) fa[find(a + 2 * n)] = find(b),fa[find(b + 2 * n)] = find(a) fa[find(a+2∗n)]=find(b),fa[find(b+2∗n)]=find(a),因为敌人的敌人是朋友嘛。
最后判断是否有矛盾即可。
如果并查集有两个根,判大小是否等于 n n n即可。
否则,从跟里找出两个的大小和等于 n n n,若有即为满足,否则不满足。
考场判断写错,惨丢
30
p
t
s
30pts
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[_];
int jj, qq[_];
void init()
{
jj = 0;
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 str[15];
int read()
{
int x = 0;
char c = getchar();
while(c < '0' || c > '9') c= getchar();
while(c >= '0' && c <= '9')
{
x = x * 10 + c - '0';
c = getchar();
}
return x;
}
void write(int x)
{
if(x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
int cc, dd;
array<int, _> c, d;
signed main()
{
T = read();
while(T--)
{
int ans = 0;
n = read();
m = read();
init();
for(int i = 1; i <= m; ++i)
{
scanf("%s", str);
int a, b;
int x = 0;
for(int j = 0, len = strlen(str); j < len; ++j)
x = (x * base % mod + (int)(str[j] - 'a' + 1)) % mod;
if(!q[x])
{
q[x] = ++k;
f[k] = x;
}
a = q[x];
scanf("%s", str);
x = 0;
for(int j = 0, len = strlen(str); j < len; ++j)
x = (x * base % mod + (int)(str[j] - 'a' + 1)) % mod;
if(!q[x])
{
q[x] = ++k;
f[k] = x;
}
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 <= k; ++i)
{
if(fa[i] == i) qq[++jj] = i;
sm[find(i)]++;
}
// cout << jj << endl;
if(jj != 2)
{
int res = 0;
bool flag = 0;
for(int i = 1; i <= jj; ++i) res += sm[qq[i]];
if(res & 1)
{
puts("NO");
continue;
}
for(int i = 1; i < 2 * n && !flag; ++i)
for(int j = i + 1; j <= 2 * n && !flag; ++j)
if(sm[i] + sm[j] == n)
{
puts("YES");
flag = 1;
}
if(!flag)
puts("NO");
}
else
{
if(sm[qq[1]] != n) puts("NO");
else puts("YES");
}
}
}