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;
}
posted @ 2024-07-16 21:08  merlinkkk  阅读(120)  评论(0)    收藏  举报