题解
彩笔只会模拟
k<=2直接输出做多那场的人数
k==3
先对三场比赛按账号数从高到低排序,则ans>=s[1][0]
然后考虑 使++ans的情况,
对于 第二场(排过序的)人数小于等于第一场 s[1][0]<=s[2][0],
把第二场中第一场出现过的删去(并查集),第二场剩下的账号可以是第一场中未在第二场出现的人的,
如果 剩下人数>第一场未在第二场中出现的人数 则 ans+=人数差
对于第三场,讨论较多
1:先删除第一场出现第二场未出现的,第一场出现第二场未出现第三场出现的账号可以和只在第二场出现的账号 是同一个人的
2:只在第一场出现的可以和只在第二场出现的账号是同一个人的
3:在第一场出现不出现在第三场的可以和只在第三场出现的账号是同一个人
对每种情况判断是否无法将两个账号归于一人,则++ans
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
#define RE register
#define FOR(i,a,b) for(RE int i=a;i<=b;++i)
#define ROF(i,a,b) for(RE int i=a;i>=b;--i)
#define sc(n) scanf("%d",&n)
#define ll long long
#define db double
//#define p pair<int,int>
using namespace std;
const int maxn = 1e5 + 5;
int m, n, k, x, y;
vector<int> s[4];
const static int MAX_V = 1e5 + 5;
int f[MAX_V], high[MAX_V], dis[MAX_V], E, V, d[MAX_V], num[MAX_V];
int vis[maxn], v[maxn];
int find(int x)
{
if (f[x] != x)return f[x] = find(f[x]);
return f[x];
}
bool same(int x, int y)
{
int fx = find(x), fy = find(y);
return fx == fy;
}
void unit(int x, int y)
{
int fx = find(x), fy = find(y);
if (x == y)return;
if (high[fx] > high[fy])f[fy] = fx;
else if (high[fx] < high[fy])f[fx] = fy;
else f[fy] = fx, ++high[fx];
}
bool cmp(const vector<int> a, const vector<int> b)
{
return a.size() > b.size();
}
int main()
{
sc(n); sc(k);
FOR(i, 1, n)f[i] = i, high[i] = 1;
FOR(i, 1, k)
{
sc(m);
s[i].push_back(m);
FOR(j, 1, s[i][0])sc(m), s[i].push_back(m);
}
sort(s + 1, s + 1 + k, cmp);
if (k <= 2)
{
printf("%d", s[1][0]);
return 0;
}
x = s[1][0];
FOR(i, 2, s[1][0])unit(s[1][1], s[1][i]);
int flag = 0;
FOR(i, 1, s[2][0])
{
if (same(s[1][1], s[2][i]))
{
--x;
f[s[2][i]] = s[2][i];
}
else
{
++y;
if (!flag)flag = s[2][i];
else unit(flag, s[2][i]);
}
}
if (!y)
{
printf("%d", s[1][0]);
return 0;
}
int ans = s[1][0], x1 = 0, yy1 = y;
FOR(i, 1, s[3][0])
{
if (same(s[1][1], s[3][i]))++x1;
else if (same(flag, s[3][i]))--yy1;
}
int sb = yy1 - x1;
if (sb < 0)sb = 0;
sb = sb + y - yy1 - x + x1;
if (sb < 0)sb = 0;
ans += sb;
if (sb < 0)sb = 0;
sb = - x1 - y + yy1 + s[1][0];
if (sb < 0)sb = 0;
sb = s[3][0] - x1 - y + yy1 - sb;
if (sb < 0)sb = 0;
ans += sb;
printf("%d", ans);
return 0;
}