*题目链接:http://codevs.cn/problem/1535/
二分图染色统计最小答案:
注意几个问题:
※※①要从每一个点都搜一遍啊,图不一定是联通的而且一号节点不一定与其他节点都联通啊,已经栽在这上面两次了,还要注意每次都取各个联通块的最小值,这样最后的答案加起来才是最小值
②数组不要开小了,一开始maxn赋的10000,结果有一个点TLE,而且我只跑了22ms,(日常吐槽codevs),后来自己造了一组数据发现是RE了,改成了10倍空间才好
③一旦发现不能继续染色,就把flg表为true,在每一次dfs之后都要写上if(!flg) return; ,要不然会超时!!
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100000+10;
int n,m,cnt,ans,tot,sum;
int fist[maxn],nxt[maxn*10];
bool color[maxn],vis[maxn],flg=true;
struct hh
{
int f,t;
}e[maxn*10];
void build(int f,int t)
{
e[++cnt]=(hh){f,t};
nxt[cnt]=fist[f];
fist[f]=cnt;
}
void dfs(int u,bool c)
{
sum++;
color[u]=c;
vis[u]=true;
for(int i=fist[u];i!=-1;i=nxt[i])
{
int v=e[i].t;
if(!vis[v])
{
if(c)
{
tot++;
dfs(v,false);
if(!flg) return;
}
else
{
dfs(v,true);
if(!flg) return;
}
}
else if(color[v]==color[u])
{
flg=false;
return;
}
}
}
int main()
{
memset(fist,-1,sizeof(fist));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i)
{
int x,y;
scanf("%d%d",&x,&y);
build(x,y);
build(y,x);
}
for(int i=1;i<=n;++i)
{
if(!flg)
{
printf("Impossible");
return 0;
}
else if(!vis[i])
{
tot=sum=0;
dfs(i,true);
ans+=min(tot,sum-tot);
}
}
ans=min(ans,n-ans);
printf("%d",ans);
return 0;
}