思路
我们把关系想成一张图,每次输入就给两个人连一条边。
因为一个人只有两种选择,所以我们在一个联通块内随便找一个点,跑一遍搜索,找出这个联通块内的答案。代码如下。
void dfs(int u,int color) {
cnt2++;// cnt2是这个连通块内的总点数
cnt1+=color;//这个是一所学校内的人
vis[u]=1;
//因为一个人不是A校就是 B校,所以对整张图进行染色
//所以一个点u假如是白色,与他相连的所有点就是黑色
for(auto v:edge[u]) {
if(!vis[v]) {
dfs(v,color^1);
/*
相当于
if(color==1) dfs(v,0)
else dfs(v,1)
*/
}
}
}
//统计答案
//因为一个人最多即为 max(cnr2-cnt1,cnt1)
主函数内只需要一个变量统计一下所有联通快的总和就行了。
讲一个有趣的性质,符合要求的图不可能包含偶环,它只能是由树和奇环组成的图,如基环树。证明我就不写了,大家可以画个图试试。
代码
最后附上代码。
#include <bits/stdc++.h>
using namespace std;
vector<int> edge[100010];
int ans, vis[100010], cnt1, cnt2;
void dfs(int u, int color)
{
cnt2++;
cnt1 += color;
vis[u] = 1;
for (auto v : edge[u])
{
if (!vis[v])
{
dfs(v, color ^ 1);
}
}
}
int main()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= m; i++)
{
int u, v;
cin >> u >> v;
edge[u].push_back(v);
edge[v].push_back(u);
}
for (int i = 1; i <= n; i++)
{
if (!vis[i])
{
cnt1 = cnt2 = 0;
dfs(i, 0);
ans += max(cnt2 - cnt1, cnt1);
}
}
cout << min(ans, n - ans) << " " << max(ans, n - ans);
return 0;
}
标签:P10378,vis,int,题解,GESP202403,dfs,color,edge,cnt1
From: https://www.cnblogs.com/merlinkkk/p/18306123