P1991 无线通讯网
#include<bits/stdc++.h>
using namespace std;
const int N=250005;
struct point{
int x,y;
}p[N];
struct edge{
int u,v;
double w;
}e[N];
int fi[N];
int n,m,num=0,sum=0;
double s;
bool cmp(edge a,edge b){
return a.w<b.w;
}
int find(int x){
if(fi[x]==x) return x;
else{
fi[x]=find(fi[x]);
return fi[x];
}
}
void kru(){
for(int i=1;i<=num;i++){
int f1=find(e[i].u);
int f2=find(e[i].v);
if(f1!=f2){
s=e[i].w;
sum++;
fi[f1]=f2;
}
if(sum>=m-n)break;//第m-n条边为排序后除了使用卫星电话线路的哨所的最大边长
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>p[i].x>>p[i].y;
}
for(int i=1;i<=m;i++){
fi[i]=i;
}
for(int i=1;i<=m;i++){
for(int j=i+1;j<=m;j++){
double z=sqrt((double)(p[i].x-p[j].x)*(p[i].x-p[j].x)+(double)(p[i].y-p[j].y)*(p[i].y-p[j].y));//计算该结点与所有其他结点的边长
e[++num].u=i;//起点
e[num].v=j;//终点
e[num].w=z; //边的长度
}
}
sort(e+1,e+1+num,cmp);//所有的边从小到大排序
kru();
printf("%.2lf",s);
return 0;
}
kruskal算法;对权重从小到大进行排序。将排序好的权重边依次加入到最小生成树中,如果加入时产生回路就跳过这条边,加入下一条边,当所有的结点都加入到最小生成树中后,就找到了这个连通图的最小生成树。
P2121 拆地毯
#include<bits/stdc++.h>
using namespace std;
const int N=250005;
struct edge{
int u,v;
double w;
}e[N];
int fi[N];
int n,m,k,sum=0,s=0;
bool cmp(edge a,edge b){
return a.w>b.w;
}
int find(int x){
if(fi[x]==x) return x;
else{
fi[x]=find(fi[x]);
return fi[x];
}
}
void kru(){
for(int i=1;i<=m;i++){
int f1=find(e[i].u);
int f2=find(e[i].v);
if(f1!=f2){
s+=e[i].w;
sum++;
fi[f1]=f2;
}
if(sum>=k)break;
}
}
int main(){
cin>>n>>m>>k;
for(int i=1;i<=m;i++){
cin>>e[i].u>>e[i].v>>e[i].w;
}
for(int i=1;i<=m;i++){
fi[i]=i;
}
sort(e+1,e+1+m,cmp);
kru();
cout<<s;
return 0;
}
将权重边从大到小排序,通过kruskal算法,每次选取最大的边,选取k条边。
P1396 营救
#include<bits/stdc++.h>
using namespace std;
const int N=250005;
struct edge{
int u,v;
double w;
}e[N];
int fi[N];
int n,m,s,t;
bool cmp(edge a,edge b){
return a.w<b.w;
}
int find(int x){
if(fi[x]==x) return x;
else{
fi[x]=find(fi[x]);
return fi[x];
}
}
void kru(){
for(int i=1;i<=m;i++){
int f1=find(e[i].u);
int f2=find(e[i].v);
if(f1!=f2){
fi[f1]=f2;
if(find(s)==find(t)){
cout<<e[i].w;
break;
}
}
}
}
int main(){
cin>>n>>m>>s>>t;
for(int i=1;i<=m;i++){
cin>>e[i].u>>e[i].v>>e[i].w;
}
for(int i=1;i<=m;i++){
fi[i]=i;
}
sort(e+1,e+1+m,cmp);
kru();
return 0;
}
在kru函数中,因为kruskal算法每次从最小边选取,所以当s区与t区第一次联通时,该边权重为道路的拥挤度最大值最小。