封锁阳光大学

https://www.luogu.com.cn/problem/P1330

  • 将无向染成两种颜色,求两种颜色中出现次数少的次数
  • 本题解用bfs染色,由于图可能不是连通的,所以外层循环遍历每个连通分图
  • 从出发点开始bfs所有它连接到的点,如果这个点的颜色和自己一样那么就不行,否则就可以入队标记并该颜色的数量加一
  • flag数组内0代表未访问,1,2分别代表标记不同的颜色
// https://www.luogu.com.cn/problem/P1330
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define MAX 100050
queue<int> q;
int head[MAX], sum[3], flag[MAX], idx;
struct Node
{
    int to, nex;
} edge[MAX * 10];
void bfs(int s)
{
    q.push(s);
    sum[1] = sum[2] = 0;
    flag[s] = 1;
    sum[flag[s]]++;
    while (!q.empty())
    {
        int from = q.front();
        q.pop();
        for (int i = head[from]; i; i = edge[i].nex)
        {
            int to = edge[i].to;
            if (flag[to] == flag[from])
            {
                printf("Impossible");
                exit(0);
            }
            if (flag[to] == 0)
            {
                flag[to] = flag[from] % 2 + 1;
                sum[flag[to]]++;
                q.push(to);
            }
        }
    }
}
void add(int u, int v)
{
    edge[++idx] = (Node){v, head[u]};
    head[u] = idx;
}
int n, m;
void input()
{
    cin >> n >> m;
    for (int i = 1; i <= m; i++)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        add(a, b);
        add(b, a);
    }
}
int ans;
int main()
{
    input();
    for (int i = 1; i <= n; i++)
        if (flag[i] == 0)
        {
            bfs(i);
            ans += min(sum[1], sum[2]);
        }
    cout << ans;
}

 

posted on 2022-08-07 09:56  樵风  阅读(34)  评论(0)    收藏  举报