边带权代码
/*
* Project: 0x41_并查集
* File Created:Tuesday, January 13th 2021, 11:36:09 am
* Author: Bug-Free
* Problem:AcWing 239. 奇偶游戏
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <unordered_map>
using namespace std;
const int N = 2e4 + 10;
int n, m;
int p[N], d[N];
unordered_map<int, int> S;
int get(int x) {
if (S.count(x) == 0) {
S[x] = ++n;
}
return S[x];
}
int find(int x) {
if (p[x] != x) {
int root = find(p[x]);
d[x] ^= d[p[x]];
p[x] = root;
}
return p[x];
}
int main() {
cin >> n >> m;
n = 0;
for (int i = 0; i < N; i++) {
p[i] = i;
}
int res = m; //如果无矛盾, 输出问题数量, 初始的时候为m
for (int i = 1; i <= m; i++) {
int a, b;
string type;
cin >> a >> b >> type;
a = get(a - 1), b = get(b); // s[a-1], s[b]
int t = 0;
if (type == "odd") {
t = 1;
}
int pa = find(a), pb = find(b);
if (pa == pb) {
if ((d[a] ^ d[b]) != t) {
res = i - 1;
break;
}
} else {
p[pa] = pb;
d[pa] = d[a] ^ d[b] ^ t;
}
}
cout << res << endl;
}
扩展域代码
/*
* Project: 0x41_并查集
* File Created:Wednesday, January 13th 2021, 12:56:07 pm
* Author: Bug-Free
* Problem:AcWing 239. 奇偶游戏
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <unordered_map>
using namespace std;
const int N = 2e4 + 10, Base = N / 2;
int n, m;
int p[N], d[N];
unordered_map<int, int> S;
int get(int x) {
if (S.count(x) == 0) {
S[x] = ++n;
}
return S[x];
}
int find(int x) {
if (p[x] != x) {
p[x] = find(p[x]);
}
return p[x];
}
int main() {
cin >> n >> m;
n = 0;
for (int i = 0; i < N; i++) {
p[i] = i;
}
int res = m; //如果无矛盾, 输出问题数量, 初始的时候为m
for (int i = 1; i <= m; i++) {
int a, b;
string type;
cin >> a >> b >> type;
a = get(a - 1), b = get(b); // s[a-1], s[b]
if (type == "even") {
if (find(a + Base) == find(b)) {
res = i - 1;
break;
}
p[find(a)] = find(b);
p[find(a + Base)] = find(b + Base);
} else {
if (find(a) == find(b)) {
res = i - 1;
break;
}
p[find(a + Base)] = find(b);
p[find(a)] = find(b + Base);
}
}
cout << res << endl;
}
林北的,考试的时候我真的能想出来完整的?
一眼闽南兄:)
大佬们,有个问题想请教一下,就是带边权那种解法,为啥我让关系是”even”的时候,t=1,就会WA,但是换成odd的时候t=1,就AC了?
我感觉,既然不管t=0还是1,下面都是用同一套代码,为啥t的对应关系就不能换过来呢?想了很久都不明白
https://www.acwing.com/user/myspace/index/87683/
题目要求的逻辑关系是偶和偶是偶,奇和奇是偶等等,改的话逻辑运算要从异或改成同或,路径压缩时也要改
因为一奇一偶拼接得奇,而0 ^ 1 == 1,因此用1来表示奇
为啥d数组不能初始化为1呢
看物理意义,d是到根的距离…一开始为0
解释了个寂寞 说了跟没说一样 根本原因是这里路径压缩时d[x]+=d[p[x]] 同时由于路径压缩某点到祖宗的路径是由点到本身联通块根结点与根节点之间路径构成 在由输入添加信息时候根节点的值都被更新 而祖宗是一定为d初值
这是递归更新的 每次d[x]都会加上祖宗的初值 如果初值不为0 会导致一直累加祖宗的初值 从而出错
为什么我初始化p数组 最后条件是到i<=N 就会错误
因为你的数组的最大范围是N - 1,你枚举到N数组就越界
为什么我没学过扩展域但是不小心想出来了/
太多细节需要会
unique咋三个地址参数
%%%%,来自一个菜菜的支持
orz
orz
大佬写的真好,终于搞懂了tql
%%%
orz
%%%%%%%%
tql
Orz
Orz
Orz
Orz
tql!感谢大佬的详细解答!
orz