牛客day3 D-Dominoes!

题目链接

Dominoes!

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

题目描述

Dominoes are rectangular tiles made of wood, bone, or plastic. They are arranged in a line at a certain distance from each other, and when the first tile is lightly tipped over, the rest of the tiles fall in succession, creating a chain reaction.

However, now you want to use the dominoes to play a different game. Given nnn dominoes, each domino has two positive integers between 111 and 10910^9109 written on it. You need to arrange these dominoes in a horizontal line so that each end of a domino matches the end of the adjacent domino (except for the two ends of the line). When arranging the dominoes, you can choose either number to be on the left or right. The task is to determine if there is an arrangement where the numbers at the touching ends of adjacent dominoes are always different. If such an arrangement exists, provide a possible solution.

输入描述:

The first line of input contains an integer nnn (1≤n≤2×105)(1\leq n\leq 2\times 10^5)(1≤n≤2×105), denoting the number of dominoes.

Then nnn lines follow. The iii-th (1≤i≤n)(1\leq i\leq n)(1≤i≤n) line contains two integers xi,yix_i,y_ixi​,yi​ (1≤xi,yi≤109)(1\leq x_i,y_i\leq 10^9)(1≤xi​,yi​≤109), denoting the numbers written on the iii-th domino.

输出描述:

If there exists a valid way to arrange dominoes, output "Yes" in the first line (without quotes). Otherwise, output ``No'' in the first line (without quotes). You can output each letter in any case (lowercase or uppercase). For example, the strings "yEs", "yes", "Yes", and "YES" will all be considered as positive replies.

If your answer is "Yes", you need to output two numbers xi,yix_i, y_ixi​,yi​ in the next nnn lines, where the iii-th (1≤i≤n1 \leq i \leq n1≤i≤n) line represents the numbers on the left and right sides of the iii-th domino in your solution, arranged from left to right.

示例1

输入

3
1 2
2 3
3 1

输出

Yes
1 2
3 2
3 1

示例2

输入

3
1 1
1000000000 1000000000
1000000000 1000000000

输出

Yes
1000000000 1000000000
1 1
1000000000 1000000000

示例3

输入

2
2 2
2 2

输出

No

题目大意

有 n张骨牌,每个骨牌上写有 2 个数字 xi , yi。

要求将 n张骨牌横着摆成一排,一共 2n个数字,保证对于相邻的不属于 同一骨牌的数字互不相同。

解题思路

输出No的情况我们可以知道当其中有个数出现的次数>=n+2因为保证对于相邻的不属于 同一骨牌的数字互不相同。

考虑从左到右构造方案,如果所有骨牌都满足 xi不等于yi,那可以按任意顺 序依次加入每一张骨牌到右侧,由此我们优先考虑如何摆放xi==yi的骨牌。

将所有 xi = yi的骨牌按照每个点数的出现次数放在一个堆中,每次选择 出现次数最大且和上一个放置的不同的骨牌放在右侧。

如果发现剩下的 xi = yi的骨牌点数都和上一个相同,不妨设该点数为 p, 从 xi!= yi的骨牌堆中挑一个 xi , yi != p的骨牌作为间隔。

可以证明,当所有数字出现次数不超过 n + 1时,上述方法一定能构造 一个合法的方案。

#include<bits/stdc++.h>
#define F first
#define S second
#define pb push_back
#define pii pair<int,int>
using namespace std;
const int maxn=1e6+3;
int n;
map<int,int> mp;
priority_queue<pii> q;
vector<pii> a,ans;
int ff(int ban) {
	if (q.empty()) return -1;
	pii t1=q.top();
	q.pop();
	if (t1.S!=ban) {
		if (t1.F>1) q.push((pii) {
			t1.F-1,t1.S
		});
		return t1.S;
	}
	if (q.empty()) {
		q.push(t1);
		return -1;
	}
	pii t2=q.top();
	q.pop();
	q.push(t1);
	if (t2.F>1) q.push((pii) {
		t2.F-1,t2.S
	});
	return t2.S;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	for (int i=1; i<=n; i++) {
		int x,y;
		cin >> x >> y;
		if (x==y) {
			mp[x]++;
		} else {
			a.pb((pii) {
				x,y
			});
		}
	}
	for (auto nd:mp) q.push((pii) {
		nd.S,nd.F
	});
	int last=-1;
	while (!q.empty()) {
		int u=ff(last);
		if (u==-1) break;
		ans.pb((pii) {
			u,u
		});
		last=u;
	}
	if (!q.empty()) {
		pii t1=q.top();
		q.pop();
		int u=t1.S,cc=t1.F;
		vector<pii> b;
		for (auto t2:a) {
			if (cc>0&&t2.F!=t2.S&&t2.F!=u&&t2.S !=u) {
				ans.pb(t2);
				ans.pb((pii) {
					u,u
				});
				cc--;
			} else {
				b.pb(t2);
			}
		}
		if (cc>0) {
			cout << "No" << endl;
			return 0;
		}
		a=b;
	}
	for (auto t1:a) {
		if (t1.F==last) {
			ans.pb((pii) {t1.S,t1.F});
		} else {
			ans.pb(t1);
			last=t1.S;
		}
	}
	cout << "Yes" << endl;
	for (auto t1:ans) cout << t1.F << ' ' << t1.S << endl;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值