按照题意,每个顶点要不放河蟹,要不不放河蟹,而且相连的顶点不能具有相同的状态。因此我们可以将其抽象成二分图,即两种相连的顶点不能染成相同的颜色,对于每一个连通图,我们使用两种颜色通过DFS将其染色,只要有一个连通图不能染色成功,就直接得到结果“NO”,因为题中可能含有多个连通图,对第i个连通图,我用2i和2i+1表示两种颜色,这个连通图放的河蟹数就是用这两种颜色染成的顶点数最小的那种颜色的数量,即min(用2i染的顶点数量,用2i+1染的顶点数量),最后每一个连通图求和就是最后的答案

#pragma GCC optimize(2)
#include<bits/stdc++.h>

using namespace std;

#define pi acos(-1.0)
#define e exp(1.0)
typedef long long ll;
const ll maxn=1e5+7;
ll N,M,col[10007];
vector<ll>V[10007];
bool flag;
ll Ku;
map<ll,ll>Ma;
void DFS(ll u,ll k)//将顶点u染成k 
{
	col[u]=k;
	ll i;
	for(i=0;i<V[u].size();i++)
	{
		ll v=V[u][i];
		if(col[v]==0)//如果没有染过,将相连的顶点染色 
		DFS(v,(k&1)?k-1:k+1);
		else if(col[v]==k)//如果染过了,并切发生了矛盾 
		{
			flag=0;//标记 
			return ;
		}
		else;
	}
	return ;
}
int main()
{
// freopen(".../.txt","w",stdout);
	ios::sync_with_stdio(false);
	memset(col,0,sizeof(col));
	cin>>N>>M;
	ll i,j;
	for(i=0;i<M;i++)
	{
		ll u,v;
		cin>>u>>v;
		V[u].push_back(v);
		V[v].push_back(u);		
	}
	flag=1;
	Ku=0;
	for(i=1;i<=N;i++)
	{
		if(col[i]==0)//可能有多个连通图 
		{
			if(!flag)//有一个不能成功染色的话直接就能得到结果了,可以减少时间 
			break;
			Ku++;
			DFS(i,2*Ku);
		}
	}
	if(!flag)//有一个连通图不能成功染色 
	{
		cout<<"Impossible"<<endl;
		return 0;
	}
	ll cnt=0,jie=0;
	for(i=1;i<=N;i++)
	Ma[col[i]]++;//将用每一种颜色染色的顶点数求出来 
	for(i=1;i<=Ku;i++)
	{
		if(!Ma[2*i])//有的连通图可能只用了一种颜色,需要将另一种颜色补充进去,便于去最小值 
		Ma[2*i]=0;
		if(!Ma[2*i+1])
		Ma[2*i+1]=0;
		jie+=min(Ma[2*i],Ma[2*i+1]); 
	}
	cout<<jie<<endl;
	return 0;
}