C. Arpa’s overnight party and Mehrdad’s silent entering(构造+二分图)

这篇文章探讨了一个有趣的编程问题,如何在满足情侣不同食物、每三人中有两人食物不同的条件下为聚会客人分配Kooft和Zahre-mar两种食物。博主通过构建二分图并染色的方法,展示了如何解决这个问题。题目涉及的数据结构和算法包括二分图定义、连通性检查和DFS搜索。
摘要由CSDN通过智能技术生成

Problem - 741C - Codeforces

请注意,阿尔帕的土地上的女孩真的很有吸引力。

阿尔帕喜欢过夜的聚会。在一次聚会中,迈尔达德突然出现。他看到n对朋友围坐在一张桌子旁。第i对包括一个男孩,坐在第i把椅子上,和他的女朋友,坐在第i把椅子上。椅子按顺时针方向编号为1至2n。每张椅子上正好有一个人坐着。


有两种类型的食物。Kooft和Zahre-mar。现在迈尔达德想知道,有没有什么方法可以为客人提供食物,以便。

每个人正好有一种食物。
没有一个男孩和他的女朋友吃同样的食物。
在任何三个坐在连续椅子上的客人中,有两个人有不同类型的食物。请注意,椅子2n和1被认为是连续的。
找到Mehrdad问题的答案。如果有可能,请找出一些满足条件的食物类型的安排。

输入
第一行包含一个整数n(1≤n≤105)--客人的对数。

接下来的n行中的第i行包含一对整数ai和bi(1≤ai,bi≤2n)--第i对中的男孩所坐的椅子的数量和他女朋友所坐的椅子的数量。保证每张椅子上正好有一个人坐着。

输出
如果没有解决方案,打印-1。

否则打印n行,其中第i行应包含两个整数,代表第i对的食物类型。该行中的第一个整数是男孩的食物类型,第二个整数是女孩的食物类型。如果有人吃了Kooft,则打印1,否则打印2。

如果有多个解决方案,则打印其中任何一个。

例子
输入复制
3
1 4
2 5
3 6
输出拷贝
1 2
2 1
1 2

题解:

题中要求情侣不可吃同样的食物,每相邻三个人 必须有两个人食物不同,联想一下二分图定义,相邻两个点的颜色不能相同

看我们是否可以构造一个二分图,情侣之间肯定要连边,代表吃的食物不同,我们先不考虑情侣之间的连边,每三个人之间有两个人食物不同,2*n个人

1 2 3 4 

假设1和2不同,连边,2和3不同,连边

如果1 3是情侣,1 3按我们的反而相同显然不行

假设1和2不同,连边,3和4不同连边,我们发现无论情侣怎么连边都是可以的

知道怎么构造后,连边,染色即可

#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
#include<map>
#include<cstring>
#include<cmath>
#include<set>
using namespace std;
#define int long long
int a[200050];
int b[200050];
vector<int> p[200050];
int st[200050];
int f = 1;
void dfs(int now,int x,int fa)
{
	st[now] = x;
	for(auto k:p[now])
	{
		if(k == fa)
		continue;
		if(st[k])
		{
			if(st[k] == x)
			{
				f = 0;
			}
		}
		else
		{
			dfs(k,3-x,now);
		}
	}
}
void solve()
{
	int n;
	cin >> n;
	for(int i = 1;i <= n;i++)
	{
		cin >> a[i] >> b[i];
		p[a[i]].push_back(b[i]);
		p[b[i]].push_back(a[i]); 
	}
	for(int i = 1;i <= 2*n;i+=2)
	{
		p[i].push_back(i+1);
		p[i+1].push_back(i);
	}
	for(int i = 1;i <= 2*n;i++)
	{
		if(!st[i])
		{
			dfs(i,1,i);
		}
	}
//	if(!f)
//	cout << "-1";
	for(int i = 1;i <= n;i++)
	{
		cout << st[a[i]]<<" "<<st[b[i]]<<"\n";
	}
}
//7 5
//1 2 4
signed main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(0);
//	cout.tie(0);
	int t = 1;
//	cin >> t;
    while(t--)
	{
		solve();
	} 
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值