Codeforces Round #805 (Div. 3)
E. Split Into Two Sets
题意
给出若干个骨牌,每个骨牌上写有两个数字,问能否把骨牌分成两堆,使得每堆中不存在重复的数字.
思路
转化成图论问题,令每个数字对应一个节点,问题从将牌分成两个集合转换成将数字分成两个集合。
对于牌(x,y),在点x和点y之间连边,表示选了x就得选y。
如果图中存在奇环,那么就无解;反之则有解。
代码
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define endl "\n" const ll N = 2e5 + 233, mod = 1e9 + 7; int n, f[N]; int a[N], b[N], sum[N]; int find(int x) { if (x == f[x]) return x; return f[x] = find(f[x]); } void check(int x, int y) { int xx = find(x), yy = find(y); if (xx != yy) { f[xx] = find(yy); } } void solve() { cin >> n; int flag = 1; for (int i = 1; i <= n; i++) f[i] = i, sum[i] = 0; map<int, int> mp; for (int i = 1; i <= n; i++) { cin >> a[i] >> b[i]; if (a[i] == b[i]) flag = 0; mp[a[i]]++; mp[b[i]]++; } for (int i = 1; i <= n; i++) { if (mp[i] >= 3) { flag = 0; break; } check(a[i], b[i]); } if (!flag) { cout << "NO" << endl; return; } for (int i = 1; i <= n; i++) { f[i] = find(f[i]); sum[f[i]]++; } for (int i = 1; i <= n; i++) if (sum[i] & 1) { cout << "NO\n"; return; } cout << "YES" << '\n'; } int main() { ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); int t; cin >> t; while (t--) { solve(); } return 0; }
F - Equate Multisets
题意
不用太听题目的话,它说不让你动a你就真不动a吗。
我们可以先把所有的a[i]和b[i]都一直除2,直到它们成为奇数为止,然后我们就可以去看b能不能去匹配a。我们可以用哈希表来把a中数的出现次数都记录下来,然后再用b去匹配,如果b[i]没有被哈希表记录,我们就继续/2,直到被哈希表被记录过,如果b[i]为0了还是没出现过,那说明这个b[i]不可能变成任意一个a,直接就是no了。如果能找到匹配的,则哈希表中这个数的出现次数–。能全部匹配成功就是yes。
为什么可以这么想呢,比如说a[i]=10,我们想得到它,那么这个b[i]就一定可以通过/2操作变成5,因为我们通过*2操作是不可能得到5这个奇数的,那么就只能是通过/2操作,如果通过/2操作得不到这个5,那这个b[i]一定无法匹配这个a[i]。为了方便我们不一个个匹配,我们直接把他们都变成最简的奇数,然后再由b[i]继续/2来看看能不能得到a[i]中的数。
思路
不用太听题目的话,它说不让你动a你就真不动a吗。
我们可以先把所有的a[i]和b[i]都一直除2,直到它们成为奇数为止,然后我们就可以去看b能不能去匹配a。我们可以用哈希表来把a中数的出现次数都记录下来,然后再用b去匹配,如果b[i]没有被哈希表记录,我们就继续/2,直到被哈希表被记录过,如果b[i]为0了还是没出现过,那说明这个b[i]不可能变成任意一个a,直接就是no了。如果能找到匹配的,则哈希表中这个数的出现次数–。能全部匹配成功就是yes。
为什么可以这么想呢,比如说a[i]=10,我们想得到它,那么这个b[i]就一定可以通过/2操作变成5,因为我们通过*2操作是不可能得到5这个奇数的,那么就只能是通过/2操作,如果通过/2操作得不到这个5,那这个b[i]一定无法匹配这个a[i]。为了方便我们不一个个匹配,我们直接把他们都变成最简的奇数,然后再由b[i]继续/2来看看能不能得到a[i]中的数。
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define endl "\n" const ll N = 2e5 + 233, mod = 1e9 + 7; map<int, int> ma; int s[N]; void solve() { ma.clear(); int n; cin >> n; for (int i = 1; i <= n; i++) { int a; cin >> a; while (a % 2 == 0) a /= 2; ma[a]++; } for (int i = 1; i <= n; i++) cin >> s[i]; for (int i = 1; i <= n; i++) { int a = s[i]; while (a % 2 == 0) a /= 2; bool flag = 0; while (a > 0) { if (ma[a] == 0) a /= 2; else { ma[a]--; flag = 1; break; } } if (!flag) { cout << "NO\n"; return; } } cout << "YES\n"; } int main() { ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); int t; cin >> t; while (t--) { solve(); } return 0; }