题目描述:
最小生成树的简单应用(kruskal算法)
满分代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=500100;
const int inf=0x3f3f3f3f;
int fa[N];
struct edge{
int u,v,w;
bool operator < (const edge &a)const{
return w<a.w;
}
}e[N];
void init(int n){
for(int i=1;i<=n;i++)
fa[i]=i;
}
int get(int x){
if(fa[x]==x) return x;
else return fa[x]=get(fa[x]);
}
void merge(int x,int y){
x=get(x);
y=get(y);
if(x!=y) fa[x]=y;
}
bool same(int x,int y){
return get(x)==get(y);
}
int main(){
int n,m,root;
scanf("%d%d%d",&n,&m,&root);
int u,v,w;
for(int i=1;i<=m;i++){
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
}
init(n);
sort(e+1,e+m+1);
int res=n;
ll ans=0,max_n=-1;
for(int i=1;i<=m&&res>1;i++){
int x=e[i].u;
int y=e[i].v;
if(same(x,y)) continue;
else{
merge(x,y);
if(e[i].w>max_n) max_n=e[i].w;
ans+=e[i].w;
res--;
}
}
printf("%lld\n",max_n);
return 0;
}
也可以利用二分的思想来做(在求最大值最小,最小值最大时经常用此种方法)
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int MAX_N=50050;//最大的节点数
const int MAX_M=100050;//最大的边数
struct edge{
int u,v,w;
bool operator < (const edge &a) const{
return w<a.w;
}
}e[MAX_M];
int fa[MAX_N];
int n,m,root;
int min_n=1e7,max_n=-1;//用来记录边的最小值和最大值
void init(int nn){
for(int i=1;i<=nn;i++)
fa[i]=i;
}
int get(int x){
if(fa[x]==x) return x;
else return fa[x]=get(fa[x]);
}
void merge(int x,int y){
x=get(x);
y=get(y);
if(x!=y) fa[x]=y;
}
bool same(int x,int y){
return get(x)==get(y);
}
int main(){
scanf("%d%d%d",&n,&m,&root);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
min_n=min(min_n,e[i].w);
max_n=max(max_n,e[i].w);
}
sort(e+1,e+m+1);
//最大值最小利用左闭右开
while(max_n>min_n){
int mid=(max_n+min_n)>>1,cnt=0;//
init(n);
for(int i=1;i<=m;i++){
if(e[i].w>mid) continue;
int x=e[i].u;
int y=e[i].v;
if(same(x,y)) continue;
else{
merge(x,y);
cnt++;
}
}
if(cnt==n-1)//可以生成树的结构
max_n=mid;
else
min_n=mid+1;
}
printf("%d\n",max_n);
return 0;
}