题解:P12222 [蓝桥杯 2023 国 Java B] 电动车
思路:
这道题一眼是用 Kruskal 求出最小生成树中权值最大的那一条边。
证明:
设 \(W\) 就是我们所求出最小生成树中权值最大的那一条边的权值。
- 因为最小生成树中任意两个顶点之间的路径是唯一的,所以从一个顶点到另一个顶点的所有可能路径中,必然会经过这条权重最大的边。
- 假设我们选择一个小于 \(W\) 的电量 \(x\),且起点在权值最大的哪一条边上的一个顶点,到达终点要经过这一条边,那么在就会因为最开始的一条边 \(W\) 比 \(x\) 大而到不了第二个点。
Kruskal 可以完美解决这个问题,因为最后那一条加入的边一定是最小生成树中最长的那一条边。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int ans;
int n,m,k,cnt,p,leb;
int fa[N],b[N],_x[N],_y[N];
struct G{
int u,ne,w;
}pic[2*N];
int find(int );
bool cmp(G ,G );
bool fx(int ,int );
void add(int ,int ,int );
int main(){
int u,v,w;
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>u>>v>>w;
add(u,v,w);
}
for(int i=1;i<=n;i++){
fa[i]=i;
}
sort(pic+1,pic+1+cnt,cmp);
int tot=0;
for(int i=1;i<=cnt;i++){
if(tot==n-1) break;
int x=pic[i].u;
int y=pic[i].ne;
if(fx(x,y)){
tot++;
ans=pic[i].w;
}
}
if(tot==n-1) printf("%d",ans);
else printf("-1");
}
bool cmp(G x,G y){
return x.w<y.w;
}
void add(int u,int v,int w){
pic[++cnt].u=u;
pic[cnt].ne=v;
pic[cnt].w=w;
}
int find(int x){
if(fa[x]==x) return x;
else return fa[x]=find(fa[x]);
}
bool fx(int x,int y){
int nx=find(x);
int ny=find(y);
if(nx==ny) return false;
else{
fa[nx]=fa[ny];
return true;
}
}