1.​​题目链接​​。这和BZOJ 1370是一个东西:镜像并查集。假设a+n和a的敌人,把a+n这个人叫做a的镜像,同理b+n是b的镜像。然后对于给定的关系x,y连边,边权就是怒气值,然后成了一个无向带权图。

(1)先说第一种搞法,也是最直观的。显然题目的要求就是再说把这个图删掉一些边使之成为二分图,那么答案具有单调性。直接二分答案,然后暴力check。check每一个值可以采用染色做,当前点赋值为1,然后和它相连的全部都是0.因为二分图有一个十分重要的性质,就是不存在奇环,如果发现染色失败,那么不行,否则输出答案即可。

(2)还是开始提到的做法,因为敌人的敌人就是朋友(其实这条性质,映射到二分图中,就是证明二分图不存在奇环的关键所在,所以这也是为什么这个题可以等价使用二分图染色做的根本原因)。所以对于a,我们需要把它合并到b+n这个集合所在的集合里,同理b合并到a+n所在的集合里。但是怎么保证最小呢?可以这样考虑:我们贪心的选择先把边权最大的安排了,然后从大到小一次安排,直到发现矛盾,说明这时已经安排好了,那么就是答案。

#include<bits/stdc++.h>
using namespace std;
const int M = 100010;
struct edge
{
int x, y;
int d;
}e[M];
int fa[2 * M];
int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
int main()
{
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= 2 * n; i++)fa[i] = i;
for (int i = 1; i <= m; i++)
{
scanf("%d%d%d", &e[i].x, &e[i].y, &e[i].d);
}
sort(e + 1, e + m + 1, [](edge x, edge y) {return x.d > y.d; });
int flag = 0;
for (int i = 1; i <= m; i++)
{
int x = find(e[i].x);
int y = find(e[i].y);
if (x == y)
{
cout << e[i].d << endl;
flag = 1;
break;
}
fa[find(x)] = find(e[i].y + n);
fa[find(y)] = find(e[i].x+n);
}
if (!flag)
{
puts("0");
}
}