#include <bits/stdc++.h>
using namespace std;
typedef struct edge // 边的结构体
{
int from, to, anger; // 起点,终点,权值
bool operator<(const edge &rhs) const // 用于优先队列
{
return anger < rhs.anger;
}
}edge;
const int MAX_V = 20002;
int n, m;
// 大顶堆
priority_queue<edge, vector<edge>, less<edge>> edges;
int dsu[MAX_V]; // 并查集本身
int val[MAX_V]; // 并查集每个结点的权值
int find(int x) // 查找最远祖先,并路径压缩,更新权值
{
if (dsu[x] != x)
{
int temp = find(dsu[x]);
val[x] = ((val[x] + val[dsu[x]]) & 1);
dsu[x] = temp;
/*
错误写法:
val[x] = ((val[x] + val[dsu[x]]) & 1);
dsu[x] = find(dsu[x]);
*/
}
return dsu[x];
}
void unite(int x, int y) // 合并,并赋予权值
{
// x对y的关系是不在一个监狱,即1,由此推算px对py的关系
int px = find(x);
int py = find(y);
dsu[px] = py; // 将px接到py下
val[px] = ((1 + val[y] - val[x]) & 1);
}
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t1, t2;
edge tmp;
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
dsu[i] = i; // 初始化并查集
}
for (int i = 0; i < m; i++)
{
cin >> tmp.from >> tmp.to >> tmp.anger;
edges.push(tmp); // 在大顶堆中放入数据
}
while (m--)
{
// 首先是条件1,若遇到两个点在同一集合,才会去判断条件2
// 条件2:如果两个点的权值相加取模是0,说明这两个点必须要在同一座监狱,不能分到两座监狱
// 即出现了矛盾,输出当前边权即可
if (find(edges.top().from) == find(edges.top().to) &&
!((val[edges.top().from] + val[edges.top().to]) & 1))
{
cout << edges.top().anger;
exit(0);
}
// 合并,权值的运算在函数中已经实现
unite(edges.top().from, edges.top().to);
edges.pop();
}
cout << '0';
return 0;
}
能够举出什么反例吗?