首页 > 其他分享 >UVA11294 Wedding 题解

UVA11294 Wedding 题解

时间:2024-10-21 11:23:44浏览次数:6  
标签:同侧 连边 int 题解 新娘 UVA11294 Wedding 新郎 SAT

洛谷题目传送门

前排提示:本题需要用到知识点 2-SAT 以及强联通分量,模板传送门 P4782 【模板】2-SAT

题目大意:

有至多 \(30\) 对夫妻将会参加一个婚宴。他们将会坐在一个长桌子的两边

新郎新娘坐在彼此相对的一端并且新娘带着一个头饰使得她看不到和她坐在同一边的人。夫妻坐在同一边是被视为“晦气”。并且这些人中还有人是通奸关系,并且新娘同时看到任何一对中的两个人也被视为“晦气”。你的工作是去安排人们坐在桌子两边从而避免任何“晦气”。

题目分析:

本题比较容易看出来是 2-SAT 的套路,考虑将 \(n\) 对夫妻拆成 \(2n\) 点,第 \(i\) 对夫妻在代码中记作为 \(i\) 和 \(i+n\), \(x\) 表示妻子与新郎同侧,\(\lnot x\) 表示丈夫与新郎同侧。

对于一对关系 \((x,y)\) 表示 \(x\) 和 \(y\) 不能坐在桌子的同一边,故 \(x\) 向 \(\lnot y\) 连边,\(y\) 向 \(\lnot x\) 连边。

最后考虑跑 Tarjan 染色,注意输出的时候需要将人物相反(即新郎同侧的是妻子,新娘同侧的是丈夫)。

注意事项:

  • 本题多测,记得清空数据
  • 编号从 \(0\) 开始,可以将所有编号 \(+1\),最后输出的时候记得 \(-1\),同理如果不改变编号用链式前向星存边的需要注意将 \(head[]\) 数组初始化为 \(-1\);
  • 新娘和新郎别忘了也要连边,若将所有的编号 \(+1\),则别忘了对应的连边 add(1,1+n);

Code:

//i 表示第 i 对的丈夫和新娘坐 i+n 表示第 i 对的妻子和新娘坐
#include<bits/stdc++.h>
using namespace std;
const int N=65;
int n,m;
int dfn[N],low[N],bel[N],cnt,tc;
bool vis[N],flag;
vector<int> g[N];
stack <int> stk;
void init()//多测初始化清空
{
	cnt=tc=flag=0;
	for(int i=1;i<N;i++) g[i].clear();//别忘了边也要清空
	memset(dfn,0,sizeof(dfn));
	memset(low,0,sizeof(low));
	memset(bel,0,sizeof(bel));
}
void Tarjan(int u)//Tarjan 模板
{
	low[u]=dfn[u]=++tc;
	vis[u]=1;
	stk.push(u);
	for(auto v:g[u])
	{
		if(!dfn[v]) Tarjan(v),low[u]=min(low[u],low[v]);
		else if(vis[v]) low[u]=min(low[u],dfn[v]);
	}
	if(low[u]==dfn[u])
	{
		++cnt;
		do
		{
			bel[u]=cnt;//染色,记录答案
			u=stk.top(),stk.pop();
			vis[u]=0;
		}while(low[u]^dfn[u]);
	}
}
int main()
{
	while(scanf("%d%d",&n,&m)&&(n+m))//多测注意结束条件为 n=0,m=0
	{
		init();//多测要清空
		g[1].push_back(1+n);//新娘向新郎连边
		while(m--)
		{
			int i,a,j,b;
			char x;
			scanf("%d%c",&i,&x),++i;//编号 +1
			a=(x=='w'?0:1);
			scanf("%d%c",&j,&x),++j;
			b=(x=='w'?0:1);
			g[i+n*(a&1)].push_back(j+n*(b^1));//省去了 if 判断过程
			g[j+n*(b&1)].push_back(i+n*(a^1));
		}
		for(int i=1;i<=n<<1;i++)
			if(!dfn[i]) Tarjan(i);
		for(int i=1;i<=n;i++)
			if(bel[i]==bel[i+n])
			{//若同时存在 x 与 ¬x 染上同样的颜色(处于同一环上),即坐在桌子的同一侧,那么输出 bad luck。
				flag=1;
				break;
			}
		if(flag)
		{
			puts("bad luck");//接上
			continue;
		}
		for(int i=2;i<=n;i++)
			printf("%d%c ",i-1,(bel[i]<bel[i+n]?'h':'w'));//注意输出
		puts(" ");
	}
	return 0;
}

标签:同侧,连边,int,题解,新娘,UVA11294,Wedding,新郎,SAT
From: https://www.cnblogs.com/lunjiahao/p/18489085

相关文章

  • SP9685 ZTC - Zombie’s Treasure Chest 题解
    洛谷题目传送门双倍经验简单题。对于空间大小为\(s1\timess2\)时,显然最多可得到的价值为\(\max(s2\timesv1,s1\timesv2)\),剩下小于\(s1\timess2\)的部分选一个占用空间大的枚举就好。时间复杂度:\(O(T\lfloor\frac{m}{\max(s1,s2)}\rfloor)\),其中\(m=n\bmo......
  • 【题解】Solution Set - NOIP2024集训Day57 字符串
    【题解】SolutionSet-NOIP2024集训Day57字符串https://www.becoder.com.cn/contest/5653「CF213E」TwoPermutations「CF961F」k-substrings「CF580E」KefaandWatch「CF504E」MishaandLCPonTree......
  • Codeforces Round 979 div2 个人题解(A~E)
    CodeforcesRound979div2个人题解(A~E)Dashboard-CodeforcesRound979(Div.2)-Codeforces火车头#define_CRT_SECURE_NO_WARNINGS1#include<algorithm>#include<array>#include<bitset>#include<cmath>#include<cstdio>#inc......
  • P11211 随机数生成器 题解
    前置知识:原根,exCRT。首先\(t=1\)是容易的,直接相邻的除一下即可。否则考虑询问除连续的\(5\)个数,分别为\(a_0,a_1,\cdots,a_4\)。首先特判掉存在\(a_i=0\)的情况,此时直接枚举\(s\)即可。我们先求出\(p\)的一个原根\(g\),设离散对数\(\log(x)=y\)表示\(g^y\equiv......
  • 牛客周赛Round64-B题题解
    牛客周赛Round64-B题题解题目描述:小红拿到了一个正整数,请你帮小红将其表示为幂(a^b)的形式。输入描述:一个正整数2<=x<=10^5输出描述:`第一行输出x。接下来每一行输出一个幂的表达式。请按指数从小到大的顺序输出。示例1输入16输出16=16^1=4^2=2^4解题思路:......
  • 【秋招笔试-支持在线评测】10.19京东秋招(已改编)-三语言题解
    ......
  • 【秋招笔试-支持在线评测】10.19小米秋招(已改编)-研发岗题解
    ......
  • [20241024] T3 题解
    细节挺多的。题意有一个长度为\(n\)的数组\(a\)和一个长度为\(m\)的队列\(q\),初始时\(q\)中的元素和为\(0\)。对\(x=1,2,\cdots,n\)进行如下操作:如果队首元素\(q_1<a_x\),则\(q\)弹出队首,将\(a_x\)插入队尾。在操作结束后,定义数组\(a\)的权值为\(q\)......
  • 2024 ICPC Asia Taiwan Online Programming Contest题解记录
    比赛链接:https://codeforces.com/gym/105383/problemA.AnimalFarm找个最大pig,然后所有比他小的其他种类生物一直加就好了#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;constllmod=1e9+7;llksm(llx,lly){ llans=1; while(y) { if(y&1)......
  • P10233 [yLCPC2024] A. dx 分计算 题解
    题目大意:题目传送门共\(T\)组测试数据,每组数据给定一个字符串\(s\)和\(Q\)次询问,按照特定的赋值方式,每次询问\(l\)到\(r\)间按这样的赋值方式的总和是多少。赋值方式如下:P可得3分p可得2分G可得1分其余字符不得分题目分析:前置知识:前缀和。(没有学过的可以先......