https://www.acwing.com/problem/content/259/
这道题蛮有趣的。
思路之一,是边带权并查集,相当于给点黑白染色,经过一条边权为1的边则改变一次颜色,规定到根节点边权和为0的为黑色。这样做的时候需要注意,合并两个不同并查集的x,y的时候,需要注意现在的黑白色只是当前连通块以内的颜色,当某次操作需要把两个不同连通块之间的黑色连在一起,则边权要带1,使子树的颜色全部翻转。
更简单的思路是,为每个人维护一个“对方集合”代表元素,每次把x,y合并的时候,假如x的“对方集合”为空则把y作为“对方集合”的第一个元素,否则把y和x的“对方集合”合并。假如某次要合并的x,y本身就在同一个集合中,直接false。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int fa[20005];
bool d[20005];
int find(int x) {
if(x == fa[x])
return x;
int rt = find(fa[x]);
d[x] ^= d[fa[x]];
return fa[x] = rt;
}
void merge(int x, int y) {
int fx = find(x);
int fy = find(y);
if(d[x] == d[y])
d[fx] ^= 1;
fa[fx] = fy;
}
bool check(int x, int y) {
int fx = find(x);
int fy = find(y);
if(fx == fy) {
if(d[x] == d[y])
return false;
return true;
}
merge(x, y);
return true;
}
struct Edge {
int u, v, w;
bool operator<(const Edge &e)const {
return w > e.w;
}
} edge[100005];
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int n;
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
fa[i] = i;
d[i] = 0;
}
int m;
scanf("%d", &m);
for(int i = 1; i <= m; ++i) {
scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].w);
}
sort(edge + 1, edge + 1 + m);
bool put = 0;
for(int i = 1; i <= m; ++i) {
if(check(edge[i].u, edge[i].v)) {
//printf("%d %d %d
", edge[i].u, edge[i].v, edge[i].w);
} else {
put = 1;
printf("%d
", edge[i].w);
break;
}
}
if(!put)
puts("0");
}
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int fa[20005];
int enemy[20005];
int find(int x) {
if(x == fa[x])
return x;
return fa[x] = find(fa[x]);
}
void merge(int x, int y) {
int fx = find(x);
int fy = find(y);
fa[fx] = fy;
}
bool check(int x, int y) {
int fx = find(x);
int fy = find(y);
if(fx == fy)
return false;
else {
if(enemy[fx] == 0)
enemy[fx] = fy;
else
merge(enemy[fx], fy);
if(enemy[fy] == 0)
enemy[fy] = fx;
else
merge(enemy[fy], fx);
return true;
}
}
struct Edge {
int u, v, w;
bool operator<(const Edge &e)const {
return w > e.w;
}
} edge[100005];
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int n;
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
fa[i] = i;
enemy[i] = 0;
}
int m;
scanf("%d", &m);
for(int i = 1; i <= m; ++i) {
scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].w);
}
sort(edge + 1, edge + 1 + m);
bool put = 0;
for(int i = 1; i <= m; ++i) {
if(check(edge[i].u, edge[i].v)) {
//printf("%d %d %d
", edge[i].u, edge[i].v, edge[i].w);
} else {
put = 1;
printf("%d
", edge[i].w);
break;
}
}
if(!put)
puts("0");
}