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
*/