封锁阳光大学【二分图染色】洛谷P1330

30 篇文章 0 订阅
3 篇文章 0 订阅

从题目中可以看出,能够完全封锁的图一定是一个二分图

只要占领一个点集(U或V)就可以封锁全部的道路
最少的河蟹数量就是较少的那个点集
上图中最少需要4只河蟹(V集合)
用dfs染色法判断是否为二分图,再用两个变量来记录不同颜色的点数
二分图中,若染源点为1,则源点的子节点染色为2,源点的,子节点子节点染色为1
如果遇到了子节点和父节点颜色相同的情况,则无法构成二分图
因为如果颜色相同,则两个点在一个点集中。而二分图的一个点集内的节点是没有边相连的,所以直接输出Impossible
由于不只有一个图,答案是每个图的最小点集之和。
PS:一开始,t1 = 1, t2 = 0。因为源点是在dfs之前提前染色,所以dfs之前,有一个点集已经有了一个点。

#include <cstdio>
#include <algorithm>
#include <cstring>
const int maxn = 10010;
int n,m,last[maxn],tot,dye[maxn],ans,t1,t2;
inline void read(int &x) { //快速读入 
    x = 0;
    char c = getchar();
    while(c<'0'||c>'9') c = getchar();
    while(c>='0'&& c<='9') x = x*10 + c-'0', c = getchar();
    return; 
}
struct Edge{
    int u,v,to;
    Edge(){}
    Edge(int u, int v, int to) : u(u), v(v), to(to) {} 
}e[2*10*maxn+10];
void addedge(int u,int v) {
    e[++tot] = Edge(u, v, last[u]);
    last[u] = tot;
}
void dfs(int u) {
    for(int i=last[u]; i; i=e[i].to) {
        int v = e[i].v;
        if(dye[v] == dye[u]) {
            printf("Impossible");
            exit(0); //无条件退出程序 
        }
        if(!dye[v]) {
            dye[v] = dye[u] == 1 ? 2 : 1;
            if(dye[v] == 1) t1++;
            else t2++;
            dfs(v);
        }
    }
}
int main() {
    read(n), read(m);
    for(int i=1; i<=m; i++) {
        int u, v;
        read(u);
        read(v);
        addedge(u,v);
        addedge(v,u); 
    }
    for(int i=1; i<=n; i++) {
        t1 = 1;
        t2 = 0;
        if(!dye[i]) dye[i] = 1, dfs(i);
        ans += std::min(t1, t2);
    }
    printf("%d", ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值