全体 集合-(图上奇偶性颜色)

72 篇文章 1 订阅

F

题意:
给你一个n点m条边k个人,然后和k个人的位置。然后每一秒每个人可以到他相邻的点去,而且必须移动,问你是否有一点可以使得这k个人在某一秒都集合在某一点。

思考:
一看树上问题,还有每秒必须走,很明显就知道有个点到其他人所在的点的距离必须奇偶,这样才能保证能集合。但是这个奇偶性怎么判断呢,用lca直接求每个点到其他点的距离是不现实的,数据太大了。所以可以直接进行染色判断,从第一个点开始,每隔一点染一色,看看最后是否k个人所在的点都是同颜色。由于这个数可能有环,所以一个点可能有两个颜色,所以再染一次。

代码:

int T,n,m,k;
int va[N];
int col[N][2];

vector<PII > v;
vector<int > e[N];

void dfs(int now)
{
	for(auto spot:e[now])
	{
		if(col[now][0])
		{
			if(!col[spot][1])
			{
				col[spot][1] = 1;
				dfs(spot);
			}
		}
		if(col[now][1])
		{
			if(!col[spot][0])
			{
				col[spot][0] = 1;
				dfs(spot);
			}
		}
	}
}
signed main()
{
	IOS;
	cin>>n>>m>>k;
	for(int i=1;i<=m;i++)
	{
		int a,b;
		cin>>a>>b;
		e[a].pb(b);
		e[b].pb(a);
	}
	for(int i=1;i<=k;i++) cin>>va[i];
	col[1][0] = 1;
	dfs(1);
	int suc1 = 1,suc2 = 1;
	for(int i=1;i<=k;i++)
	{
		if(col[va[i]][0]==0) suc1 = 0;
		if(col[va[i]][1]==0) suc2 = 0;
	}
	if(suc1||suc2) cout<<"YES\n";
	else cout<<"NO\n";
	return 0;
}

总结:
将复杂的问题多多简单化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值