对点进行染色,将一条道路的两端染成不同的颜色,如果有冲突则“Impossible”,没有冲突则比较两种颜色的点的数量,选较小者累加。
Code:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
struct node{int x,y,next;};
node a[200010];
int first[200010];
int q[500010];
int c[200010];
int h[500010];
bool v[200010],vis[200010];
int n,m,st,ed,len=0,ans=0;
void ins(int x,int y)
{
len++;a[len].x=x;a[len].y=y;a[len].next=first[x];first[x]=len;
len++;a[len].x=y;a[len].y=x;a[len].next=first[y];first[y]=len;
}
void dfs(int t)
{
int wh=1,bl=0;
memset(v,false,sizeof(v));v[t]=true;
st=1;ed=2;
q[st]=t;c[t]=1;
while(st!=ed)
{
int x=q[st];
for(int i=first[x];i;i=a[i].next)
{
int y=a[i].y;
if(c[y]==0)
{
c[y]=c[x]*(-1);
if(c[y]==1) wh++;
else bl++;
}
else
{
if(c[y]==c[x])
{
printf("Impossible");
exit(0);
}
}
if(!v[y])
{
v[y]=true;
vis[y]=true;
q[ed++]=y;
}
}
st++;
}
ans+=min(wh,bl);
}
int main()
{
memset(c,0,sizeof(c));
memset(vis,false,sizeof(vis));
memset(first,0,sizeof(first));
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d %d",&x,&y);
ins(x,y);
}
for(int i=1;i<=n;i++)
{
if(!vis[i])
{
vis[i]=true;
dfs(i);
}
}
printf("%d",ans);
}