ICM Technex 2017 and Codeforces Round #400 (Div. 1 + Div. 2, combined) D. The Door Problem 并查集

博客围绕一道题目展开,题目是有n个房间由m个开关控制,每个房间由两个开关控制且有初始解锁状态,需判断能否让所有房间解锁。题解给出用并查集的方法,还提到可用2 - sat做,后续复习完2 - sat会再写一遍。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目: https://codeforces.com/contest/776/problem/D

题意: 有n个房间,由m个开关控制。每个房间一定是由两个开关控制。每个房间有一个初始的是否解锁的状态。问你能否让所有房间都解锁。

题解: 若控制一个房间的开关为a,b。一个开关若开为a,不开为a+m。则若房间原来开着,就为(a,b)或(a+m,b+m)。原来没开就为(a,b+m)或(a+m,b)。用并查集并起来,最后如果有a和a+m在同一个集合就为NO。

可是就是想不到啊,qaq怎么这么菜啊

还可以用2-sat做,到时候复习完2-sat再写一遍吧

#include<bits/stdc++.h>
using namespace std;
int r[100010],y[100010][3],ly[100010],father[200110];
int findfather(int k){if(father[k]==k)return father[k];else return father[k]=findfather(father[k]);}
void ak(int aa,int bb)
{
	int a1=findfather(aa);
	int b1=findfather(bb);
	if(a1!=b1)father[a1]=b1;
}
int main()
{
	int n,m,i,j,lx,x,k1,k2;
	scanf("%d %d",&n,&m);
	for(i=1;i<=n;i++)scanf("%d",&r[i]);
	for(i=1;i<=m;i++)
	{
		scanf("%d",&lx);
		for(j=1;j<=lx;j++)
		{
			scanf("%d",&x);
			y[x][++ly[x]]=i;
		}
	}
	
	for(j=1;j<=2*m;j++)father[j]=j;
	for(i=1;i<=n;i++)
	{
		k1=y[i][1];k2=y[i][2];
		if(r[i]==0)
		{
			ak(k1,k2+m);
			ak(k1+m,k2);
		}
		else
		{
			ak(k1,k2);
			ak(k1+m,k2+m);
		}
	}
	for(i=1;i<=m;i++)if(findfather(i)==findfather(i+m)){printf("NO");return 0;}
	printf("YES");
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值