题目:https://www.luogu.org/problemnew/show/P1330
解题思路:
1、点数<=10000,边数<=100000,因此采用前向星存图。
2、图可能不至一个连通块。遍历点,若点染色为0,则bfs。bfs内以前向星遍历边,染色边的端点,并记录染色1与2的计数。
AC代码:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int n,m,x,y;
struct Edge{
int from,to,next;
};
Edge edge[200005];
int num=0,head[10002];
int flg,vis[10002];
int que[10002];
int s[3],ans=0;
void join(int from,int to){
edge[++num].next=head[from];
edge[num].from=from;
edge[num].to=to;
head[from]=num;
}
void bfs(int x){
vis[x]=1;
s[1]++;
int hd=0,tl=1;
que[1]=x;
while(hd<tl){
hd++;
int from=que[hd];
for(int i=head[from];i!=-1;i=edge[i].next){
int to=edge[i].to;
if(vis[to]==0){
if(vis[from]==1)vis[to]=2;
else vis[to]=1;
s[vis[to]]++;
que[++tl]=to;
}
else if(vis[to]==vis[from]){
cout<<"Impossible\n";
flg=1;
break;
}
}
if(flg)break;
}
}
int main(){
memset(head,-1,sizeof(head));
cin>>n>>m;
for(int i=0;i<m;i++){
cin>>x>>y;
join(x,y);join(y,x);
}
for(int i=1;i<=n;i++)
if(vis[i]==0){
s[1]=s[2]=0;
bfs(i);
if(flg)break;
ans += s[1]<s[2]?s[1]:s[2];
}
if(!flg)cout<<ans<<endl;
return 0;
}