luogu P1330 封锁阳光大学

Posted fructose-ryllis

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu P1330 封锁阳光大学相关的知识,希望对你有一定的参考价值。

封锁阳光大学

标签:二分图染色

这题是真的难想……知道是二分图染色就明白了,虽然之前没学好

题面表面说是一张图,实际上……嗯,很多连通子图。

思路

建图(large Rightarrow)枚举点(large Rightarrow)广搜染色(large Rightarrow)判定合法不合法(large Rightarrow)用更小的染色值更新答案

建图

基本操作,前向星

枚举点

因为是多个连通子图构成的,需要枚举每一个点进行判定,如果这个点之前被染过色了就不需要理它了。

广搜染色&判定合不合法&更小的值更新答案

每次广搜都先将初始点染成1,向外周扩展一步,就染成颜色2,换色可以用取模来实现。

注意不要拿染色来当标记……我估计是没处理好吧,用染色当标记广搜挂掉了,所以就多开了一个vis数组来标记一下入队后出队的元素,如果中途发现我们找到了一个染过色的点,如果这个点没出过队,而且还和队头的点的颜色一样,很明显,我们没有办法做到题目要求,因为两点颜色相同就说明:我们要么两个点都放河蟹要么两个点都不放——两个都是不合法的。

至于这个答案是不是最小呢?只要合法,我们就只需要选择黑色和白色中数量比较小的那一个就好了。

代码

//by Saber Alter Official
//Erishikigal & Ishtar
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <queue>
//标签:广搜染色 
typedef long long ll;
typedef unsigned long long ull;

const int N = 10015, M = 100015;

struct node {
    int next, to;
}edge[M << 1];
int head[N], cnt;
inline void add_edge(int u, int v) {
    edge[++cnt].to = v;
    edge[cnt].next = head[u];
    head[u] = cnt;
}

int n, m, ans;
bool Cant, vis[N];
int color[N], sum[5];

inline void BFS(int S) {
    std::queue<int> Que;
    Que.push(S);
    while(!Que.empty()) {
        int u = Que.front();
        Que.pop();
        vis[u] = true;
        
        for(int i = head[u];i;i = edge[i].next) {
            int v = edge[i].to;
            if(vis[v]) continue;
            
            if(color[v] == color[u]) {
                Cant = true;
                break;
            }
            
            color[v] = (color[u] % 2) + 1;
            
            sum[color[v]]++;
            
            Que.push(v);
        }
    }
}

void init() {
    scanf("%d %d", &n, &m);
    for(int i = 1;i <= m;i++) {
        int _u, _v;
        scanf("%d %d", &_u, &_v);
        add_edge(_u, _v);
        add_edge(_v, _u);
    }
}

int main() {
    init();
    
    for(int i = 1;i <= n;i++) {
        if(!color[i]) {
            color[i] = 1;
            sum[1] = 1;
            sum[2] = 0;
            BFS(i);
            if(Cant) {
                printf("Impossible
");
                return 0;
            }
            ans += std::min(sum[1], sum[2]);
        }
    }
    
    printf("%d
", ans);
    
    return 0;
}

以上是关于luogu P1330 封锁阳光大学的主要内容,如果未能解决你的问题,请参考以下文章

luogu P1330 封锁阳光大学--图上染色

luogu P1330 封锁阳光大学

Luogu P1330 封锁阳光大学 (黑白染色)

luogu P1330 封锁阳光大学

洛谷——P1330 封锁阳光大学

Luogu P1330 封锁阳光大学Dfs By cellur925