题意:
思路:
观察题目,我们可以将题意简化为:一个无向图中,每条边具有不同的权重,我们需要找到一个最优生成树,使得这个树中的最大边权最小。因此题目就转化成了最小生成树问题。
采用结构体来存储边,结构体里的数据变量为两顶点和边的权重,将边存入到一个边数组里,采用kruskal算法求得最小生成树,结果便是这棵最小生成树中的最大边的值。
(关于kruskal算法的注意点,可以看我之前写的blog: https://blog.csdn.net/FoxMakarov/article/details/105169919)
总结:
有时候题目会非常繁琐,我们需要将复杂的题意转化为简单的问题
求得最小生成树问题可以采用kruskal算法。
代码:
#include<stdio.h>
#include<algorithm>
int par[50001] = { 0 };
int Rank[50001] = { 0 };
struct Edge
{
int u;
int v;
int w;
Edge(int _u = 0, int _v = 0, int _w = 0) :u(_u), v(_v), w(_w) {}
Edge(const Edge& t) :u(t.u), v(t.v), w(t.w) {}
bool operator<(const Edge& t)const
{
return w < t.w;
}
};
int find(int i)
{
if (i == par[i])
return i;
else return par[i] = find(par[i]);
}
bool unite(int i, int j)
{
int par1 = find(i);
int par2 = find(j);
if (par1 == par2)return false;//****************************已经在一个并查集里了
if (Rank[par1] < Rank[par2])
{
Rank[par2] += Rank[par1];
par[par1] = par2;
}
else
{
Rank[par1] += Rank[par2];
par[par2] = par1;
}
return true;
}
Edge edge[100001];
int main()
{
int n;
long long m;
int root;
scanf_s("%d %lld %d", &n, &m, &root);
for (int i = 0; i < n; i++)
{
par[i] = i;
Rank[i] = 1;
}
for (long long i = 0; i < m; i++)
{
int u, v;
long long w;
scanf_s("%d %d %lld", &u, &v, &w);
edge[i] = Edge(u, v, w);
}
std::sort(edge, &edge[m]);
long long ans = -1;
for (int i = 0; i < m; i++)
{
if (unite(edge[i].u, edge[i].v))
{
if (ans < edge[i].w)ans = edge[i].w;
}
}
printf("%lld", ans);
}
}