P1330 封锁阳光大学

题解:

要求的是对点涂色,保证涂色的点不相邻,但是必须只隔一个。【保证涂满】

直接暴力涂色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();
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值