P1330 封锁阳光大学 - 二分图染色

传送门

根据题意可知二分图染色。若无法被染成二分图,输出Impossible;反之,对于每个二分图,记录两种颜色的点的个数,取min后记录答案中。

注意,图可能不连通。因此对于每个二分图,都要进行取min操作,而不是对整个图染色后取min。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
inline void r(int &x){
    x=0;
    char ch=getchar();
    bool f=0;
    while(!isdigit(ch)) f=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    if(f) x=-x;
}
const int N=10000+100,M=100000+100;
struct node{
    int to,nxt;
}e[M<<1];
int head[N],tot;
inline void add(int u,int v){
    e[++tot]=(node){v,head[u]};
    head[u]=tot;
}
int col[N],colv[4];
bool dfs(int u,int c){
    col[u]=c;colv[c]++;
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].to;
        if(col[v]==col[u]) return false;
        if(!col[v]){
            if(!dfs(v,3-c)) return false;
        }
    }
    return true;
}
int main(){
    int n,m;
    r(n);r(m);
    for(int i=1;i<=m;i++){
        int u,v;
        r(u);r(v);
        add(u,v);add(v,u);
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        if(!col[i]) {
            colv[1]=colv[2]=0;
            if(!dfs(i,1)){
                printf("Impossible");return 0;
            }
            else ans+=min(colv[1],colv[2]);
        }
    }
    //对于每个联通块分别处理 !!!
    printf("%d",ans);
    return 0;
}
/*
6 6
1 2
2 3
4 3
5 4
5 6
1 6
*/