题解:
要求的是对点涂色,保证涂色的点不相邻,但是必须只隔一个。【保证涂满】
直接暴力涂色0和1,由于存在非连通的情况,需要遍历所有子图。
数出0的的个数和1的个数,较少的被加上贡献。
输出贡献。
如果中途出现冲突,比如下一个涂0但是已经被涂成1。【这种情况假如0是答案,那么目前所在点1是应该涂色但没有涂色的】
【1是答案,那么两个1必定是相邻的,不符合】
所以一旦出现冲突,答案一定是impossible。
代码:
遍历的时候采用了dfs判断有没有经历父节点的方法,对双向边遍历有奇效。【目前开始尝试】
#include<bits/stdc++.h>
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
const int MAXN = 901000;
struct Edge
{
int from,to,dist;
Edge(){}
Edge(int _from,int _to,int _dist):from(_from), to(_to),dist(_dist) {}
};
vector<Edge>g[MAXN];
int n,m;
int flag[MAXN];
bool ok = true;
void insert(int u,int v,int w)
{
g[u].push_back(Edge(u,v,w));
g[v].push_back(Edge(v,u,w));
}
void dfs(int u,int record,int f,int &black,int &white)
{
if(!ok)return ;
record^=1;
for(int i=0;i<g[u].size();i++)
{
Edge &e=g[u][i];
if(e.to==f)continue;
if(flag[e.to]==record)continue;
else if(flag[e.to]==-1)
{
flag[e.to]=record;
if(record)black++;else white++;
}
else
{
ok = false;
return ;
}
dfs(e.to,record,u,black,white);
}
}
void solve()
{
cin>>n>>m;
FOR(i,1,m)
{
int x,y;
scanf("%d%d",&x,&y);
insert(x,y,1);
}
memset(flag,-1,sizeof(flag));
int ans=0,white,black;
FOR(i,1,n)
if(flag[i]==-1)
{
white=0,black=1;
flag[i]=1;
dfs(i,1,-1,black,white);
ans+=min(black,white);
}
if(ok)cout<<ans<<endl;
else puts("Impossible");
}
int main()
{
solve();
}