2024-07-16 21:08阅读: 50评论: 0推荐: 0

P10378 [GESP202403 七级] 交流问题题解

思路

我们把关系想成一张图,每次输入就给两个人连一条边。

因为一个人只有两种选择,所以我们在一个联通块内随便找一个点,跑一遍搜索,找出这个联通块内的答案。代码如下。

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

本文作者:merlinkkk

本文链接:https://www.cnblogs.com/merlinkkk/p/18306123

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   merlinkkk  阅读(50)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开