思路1
这个题干看起来比较复杂,但是细读后就能明白,这个题会给定一个图,我们要找一个图的最小生成树,这棵生成树要保证其中的最大边权最小(这种树叫做瓶颈生成树)。
可以证明,最小生成树一定是瓶颈生成树(反之不真)。因此,我们可以直接求最小生成树并找最大边权即可。
思路2
最小生成树或许不太容易想到,这个题也可以用二分答案的方法。给定一个最大边权的值,我们是容易判断是否存在生成树的(首先对所有边权排序,然后就比较容易)。而答案是最大边权的最小值,具有单调性,所以二分可行。
完整代码(求最小生成树)
#include<iostream>
#include<queue>
#define MAX 50005
using namespace std;
int pre[MAX];
int num[MAX];
int find(int x)
{
if(pre[x] == x) return x;
return (pre[x] = find(pre[x]));
}
void unite(int x, int y)
{
int fx = find(x);
int fy = find(y);
if(fx == fy) return;
if(num[fx] > num[fy]) swap(fx, fy);
pre[fx] = fy;
num[fy] += num[fx];
}
struct Edge{
int u;
int v;
int t;
bool operator < (const Edge &e) const
{
return (t > e.t);
}
};
priority_queue<Edge> pq;
int main ()
{
ios::sync_with_stdio(false);
int n, m, root;
cin>>n>>m>>root;
for(int i=0;i<=n;i++)
{
pre[i]=i;
num[i]=1;
}
for(int i=0;i<m;i++)
{
int u,v,t;
cin>>u>>v>>t;
pq.push({u,v,t});
}
int res=-1;
int cnt=1;
while(cnt < n)
{
Edge e;
while(true)
{
e=pq.top(); pq.pop();
if(find(e.u) != find(e.v)) break;
}
if(res < e.t) res=e.t;
unite(e.u, e.v);
cnt++;
}
cout<<res<<endl;
return 0;
}
完整代码(二分答案)
#include<bits\stdc++.h>
using namespace std;
int pre[50005];
int r[50005];
int find(int x)
{
if(pre[x] == x) return x;
else return (pre[x] = find(pre[x]));
}
void unite(int x, int y)
{
int fx = find(x);
int fy = find(y);
if(fx == fy) return;
if(r[fx] > r[fy]) swap(fx, fy);
pre[fx] = fy;
r[fy] += r[fx];
}
int N, M, root;
struct Edge{
int u;
int v;
int w;
bool operator < (const Edge &e) const
{
return w < e.w;
}
}e[100005];
bool check(int x)
{
for(int i=1;i<=N;i++) pre[i]=i, r[i]=1;
int n=1;
for(int i=0;i<M, e[i].w <=x;i++)
{
int fv = find(e[i].v);
int fu = find(e[i].u);
if(fv != fu) unite(fv, fu), n++;
if(n == N) return true;
}
return false;
}
int binS()
{
int l=0, r=1000001;
int mid;
while(l < r)
{
mid = l+r>>1;
if(check(mid)) r = mid;
else l = mid + 1;
}
return r;
}
int main()
{
cin>>N>>M>>root;
for(int i=0;i<M;i++) cin>>e[i].u>>e[i].v>>e[i].w;
sort(e, e+M);
cout<<binS();
return 0;
}