解题思路
采用二分图黑白染色的方法,每次要新加进一个点,就把他和他相连的点大上不同的标记(黑白染色),表示他们属于不同集合, 把黑白两方中个数少的累加进答案就好了。
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<map>
#include<queue>
#define ll unsigned long long
#define ldb long double
using namespace std;
int n,m,x,y,ans,w1,w2,k,head[200010],v[200010];
bool flag=1;
struct c
{
int x,next;
} a[200010];
void add(int x,int y)
{
a[++k].x=y;
a[k].next=head[x];
head[x]=k;
}
void dfs(int x,int fa)
{
for(int i=head[x]; i; i=a[i].next)
{
int y=a[i].x;
if(!flag)return;
if(v[y]==v[x])
{
printf("Impossible\n");
flag=0;
return;
}
if(!v[y])
{
v[y]=v[fa];
if(v[fa]==1)w1++;
else w2++;
dfs(y,x);
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1; i<=m; i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
v[0]=2;
for(int i=1; i<=n; i++)
{
if(!v[i])
{
v[i]=1;
w1=1,w2=0;
dfs(i,0);
ans+=min(w1,w2);
}
}
if(!flag)return 0;
printf("%d",ans);
}
/*
30 12
18 12
11 5
5 30
15 23
28 2
12 2
3 26
7 28
25 22
4 3
27 22
6 9
*/