题目大意:

题目链接:​​https://www.luogu.org/problemnew/show/P1330​

给出一个图(不一定联通),每条边的两个端点都仅能选择一个点。求最小选择数。


思路:

将这个图黑白染色,对于每个连通图,选择更少的那种颜色并求和。

搜索的方法有很多,我用的是广搜。


代码:

#include <cstdio>
#include <cstring>
#include <queue>
#define N 10100
#define M 100100
using namespace std;

int n,m,sum1,sum2,ans,color[N],x,y,tot,head[N];

struct edge
{
int next,to;
}e[M*2];

void add(int from,int to)
{
e[++tot].to=to;
e[tot].next=head[from];
head[from]=tot;
}

bool bfs(int i)
{
queue<int> q;
q.push(i);
color[i]=1;
sum1=1;
while (q.size())
{
int u=q.front();
for (int i=head[u];~i;i=e[i].next)
if (!color[e[i].to])
{
if (color[u]==1) color[e[i].to]=2,sum2++;
else color[e[i].to]=1,sum1++; //黑白染色
q.push(e[i].to);
}
else
if (color[e[i].to]==color[u]) //冲突
{
printf("Impossible");
return false;
}
q.pop();
}
return true;
}

int main()
{
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
for (int i=1;i<=n;i++)
if (!color[i])
{
if (!bfs(i)) return 0;
ans+=min(sum1,sum2);
sum1=0;
sum2=0;
}
printf("%d\n",ans);
return 0;
}