【洛谷P1330】封锁阳光大学【BFS】

题目大意:

题目链接: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;
}
posted @ 2018-09-22 16:44  全OI最菜  阅读(147)  评论(0编辑  收藏  举报