B交通改造:Kruskal 思路:1.接受改造的道路能够令所有的交叉路口直接或间接相连2.并且改造的道路数量应尽可能的少.这两条信息提示我们最终形成的是一颗生成树。但并非是最小生成树,而是最大边权最小生成树。那么只需要二分答案,每次看是否能够形成一棵生成树即可。形成的生成树的充要条件为共有n-1条边
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010, M = 200010, INF = 0x3f3f3f3f;
int n, m;
int p[N];
struct Edge
{
int a, b, w;
bool operator< (const Edge& W)const
{
return w < W.w;
}
}edges[M];
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
int kruskal(int x)
{
for (int i = 1; i <= n; i++) p[i] = i; // 初始化并查集
int res = 0, cnt = 0;
for (int i = 0; i < m; i++)
{
int a = edges[i].a, b = edges[i].b, w = edges[i].w;
a = find(a), b = find(b);
if (a != b && w <= x)
{
p[a] = b;
res += w;
cnt++;
}
}
if (cnt < n - 1) return 0;
return 1;
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 0; i < m; i++)
{
int a, b, w;
scanf("%d%d%d", &a, &b, &w);
edges[i] = { a, b, w };
}
sort(edges, edges + m);
int l = 0, r = 10000;
while (l < r)
{
int mid = (l + r ) / 2;
if (kruskal(mid) ==0)
{
l = mid + 1;
}
else r = mid;
}
cout << n - 1 << " ";
cout << l << endl;
return 0;
}