ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Codeforces Round #805 (Div. 3)

2022-07-11 16:06:35  阅读:145  来源: 互联网

标签:cnt ok ++ LL Codeforces int 骨牌 Div 805


比赛链接:

https://codeforces.com/contest/1702

E. Split Into Two Sets

题意:

\(n\)(\(n\) 为偶数)张多米诺骨牌,每张骨牌有两个数字(数字范围为 1 到 \(n\)),问是否能将所有的骨牌分成两堆,每堆中的数字没有重复。

思路:

容易知道最后划分出来的两堆骨牌覆盖了 1 到 \(n\) 的所有数字,即每个数字在每堆中只有一个。
所以可以将所有的数字对应的骨牌编号记录下来,同一个数字对应的两张骨牌要不在一个堆中,满足二分图的性质。
将一张骨牌所对应的两个编号之间建立一条边,通过染色法判断是不是二分图。

#include <bits/stdc++.h>
using namespace std;
#define LL long long
void solve(){
	LL n;
	cin >> n;
	vector <LL> g[n + 1], cnt(n + 1), G[n + 1];
	bool ok = true;
	for (int i = 0; i < n; i ++ ){
		LL a, b;
		cin >> a >> b;
		g[a].push_back(i);
		g[b].push_back(i);
		if (a == b){
			ok = false;
		}
		cnt[a] ++ ;
		cnt[b] ++ ;
		if (cnt[a] >= 3 || cnt[b] >= 3){
			ok = false;
		}
	}
	if (!ok){
		cout << "NO\n";
		return;
	}
	for (int i = 1; i <= n; i ++ ){  //建图
		LL u = g[i][0], v = g[i][1];
		G[u].push_back(v);
		G[v].push_back(u);
	}
	vector <LL> color(n + 1);
	function<bool(LL, LL)> dfs = [&] (LL u, LL c){  //染色法判断二分图
		color[u] = c;
		for (auto v : G[u]){
			if (!color[v]){
				if (!dfs(v, 3 - c))
					return false;
			}
			else{
				if (color[v] == c){
					return false;
				}
			}
		}
		return true;
	};
	for (int i = 1; i <= n; i ++ ){
		if (!color[i]){
			if (!dfs(i, 1)){
				cout << "NO\n";
				return;
			}
		}
	}
	cout << "YES\n";
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	LL T;
	cin >> T;
	while(T -- )
		solve();
	return 0;
}

让骨牌对应的两个数字产生联系,它们最后会形成一个环,要做的就是将这个环拆成两段,分别放到两个堆中,即环的长度为偶数,所以可以通过并查集来做,判断每个环的长度即可。

#include <bits/stdc++.h>
using namespace std;
#define LL long long
struct dsu{
	LL n;
	vector <LL> p, sz;
	dsu(LL n) : n(n){
		p.resize(n + 1);
		sz.resize(n + 1);
		iota(p.begin(), p.end(), 0LL);
		for (int i = 1; i <= n; i ++ )
			sz[i] = 1;
	}
	LL get(LL x){
		return (x == p[x] ? x : (p[x] = get(p[x])));
	}
	void unite(LL x, LL y){
		x = get(x);
		y = get(y);
		if (x != y){
			p[x] = y;
			sz[y] += sz[x];
		}
	}
};
void solve(){
	LL n;
	cin >> n;
	dsu d(n);
	vector <LL> cnt(n + 1);
	bool ok = true;
	for (int i = 0; i < n; i ++ ){
		LL x, y;
		cin >> x >> y;
		cnt[x] ++ ;
		cnt[y] ++ ;
		if (x == y){
			ok = false;
		}
		d.unite(x, y);
	}
	if (!ok){
		cout << "NO\n";
		return;
	}
	for (int i = 1; i <= n; i ++ ){
		if (cnt[i] != 2){
			cout << "NO\n";
			return;
		}
	}
	for (int i = 1; i <= n; i ++ ){
		if (i != d.get(i)){
			if (d.sz[d.get(i)] & 1){
				cout << "NO\n";
				return;
			}
		}
	}
	cout << "YES\n";
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	LL T;
	cin >> T;
	while (T -- )
		solve();
	return 0;
}

F. Equate Multisets

题意:

给定两个序列 \(a\) 和 \(b\),可以选择 \(b\) 中的元素进行除 2 或者乘 2 操作,问是否能让 \(b\) 与 \(a\) 中的元素相同。

思路:

对于一个元素 * 2 是不会改变奇偶性的,但是 / 2 可能会改变,可以将所有的偶数中的 2 全部去掉,这样子所有的元素就都是奇数了。
能够匹配的元素进行匹配,不能够匹配的一直 / 2,直到不能除为止,若始终无法匹配,说明没有办法让两个序列元素相同。

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
void solve(){
	LL n;
	cin >> n;
	map <LL, LL> cnt;
	for (int i = 0; i < n; i ++ ){
		LL x;
		cin >> x;
		while(x % 2 == 0){
			x >>= 1;
		}
		cnt[x] ++ ;
	}
	vector <LL> b(n);
	for (int i = 0; i < n; i ++ ){
		cin >> b[i];
		while(b[i] % 2 == 0){
			b[i] >>= 1;
		}
	}
	for (int i = 0; i < n; i ++ ){
		while(cnt[b[i]] == 0 && b[i] > 0){
			b[i] /= 2;
		}
		if (b[i] == 0){
			cout << "NO\n";
			return;
		}
		cnt[b[i]] -- ;
	}
	cout << "YES\n";
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	LL T;
	cin >> T;
	while(T -- )
		solve();
	return 0;
}

标签:cnt,ok,++,LL,Codeforces,int,骨牌,Div,805
来源: https://www.cnblogs.com/Hamine/p/16465518.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有