最小瓶颈生成树(POJ - 2349Arctic Network)

思路:
求最小生成树的时候记录下每一条边,然后逆序排序,然后跳出第s的边,相当于前(s-1)大的边免费。

Arctic Network
Prim算法:
在这里插入图片描述

Solution1:

#include<stdio.h>
#include<iostream>
#include<cmath>
#include<math.h>
#include<string>
#include<string.h>
#include<algorithm>
#define ll long long
using namespace std;
const int size=500+5;
double a[size][size];
double pos_max_cost[size],w[size];
int n,m,cnt; //a为邻接矩阵
bool v[size];

struct Dot {
    int x,y;
}dots[size];
double get_dis(Dot a,Dot b){
    int dx = a.x-b.x,dy=a.y-b.y;
    return sqrt(dx*dx+dy*dy);
}

void prim(){
    cnt=0;
    memset(v, 0, sizeof(v));
    w[1]=0;
    v[1]=1;
    //初始化cost数组
    for(int i=2;i<=n;i++){
        w[i]=a[i][1];
    }
    //再加入n-1个点
    for(int j=1;j<=n-1;j++){
        double mincost= 1<<30;int minid=2;
        //找出花费最小的那个点
        for(int i=2;i<=n;i++){
            if(!v[i] && w[i]<mincost){
                mincost=w[i];minid=i;
            }
        }
        pos_max_cost[++cnt]=mincost;
        v[minid]=1;
        //更新花费数组
        for(int i=2;i<=n;i++) w[i]=min(w[i],a[i][minid]);
    }
}

int main(){
    int t,s,p;
    cin>>t;
    while(t--){
        cin>>s>>p;
        n=p;
        for(int i=1;i<=p;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            dots[i].x=x;dots[i].y=y;
        }
        for(int i=1;i<p;i++){
            for(int j=i+1;j<=p;j++){
                a[i][j]=a[j][i] = get_dis(dots[i], dots[j]);
            }
        }
        prim();
        sort(pos_max_cost+1,pos_max_cost+p);
        reverse(pos_max_cost+1, pos_max_cost+p);
        printf("%.2f\n",pos_max_cost[s]);
    }
    return 0;
}

Solution2:
Kruskal算法
在这里插入图片描述

#include<stdio.h>
#include<iostream>
#include<math.h>
#include<string>
#include<string.h>
#include<algorithm>

using namespace std;
const int maxn=800;  //数组要开够
int n,m,bm,fa[maxn],ncase,s;
double  cost[maxn+5];
struct Dot{
    int x,y;
}dots[maxn];
struct Edge{
    int u,v;
    double cost;
}t[maxn*maxn/2];

double get_dis(int i,int j){
    double dx=dots[i].x-dots[j].x;
    double dy=dots[i].y-dots[j].y;
    return sqrt(dx*dx+dy*dy);
}

bool cmp(Edge a,Edge b){
    return a.cost<b.cost;
}

int find(int x){
    return (x==fa[x])?x:fa[x]=find(fa[x]);
}
void merge(int x,int y){
    fa[find(x)]=find(y);  //合并代表元
}

void init()
{
    for(int i=1;i<=n;i++) fa[i]=i;
    memset(cost,0,sizeof(cost));
}


int main(){
    cin>>ncase;
    while(ncase--)
    {
        cin>>s>>n;
        //初始化点集
        for(int i=1;i<=n;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            dots[i].x=x;dots[i].y=y;
        }
        m=0;//初始化边集
        for(int i=1;i<n;i++){
            for(int j=i+1;j<=n;j++){
                t[++m].u=i;t[m].v=j;
                t[m].cost=get_dis(i, j);
            }
        }
        //初始化并查集
        init();
        sort(t+1,t+m+1,cmp);
        int cnt=0;
        //已经建好的,直接merge就好
        for(int i=1;i<=m;i++){
            int u=t[i].u,v=t[i].v;
            if(find(u)!=find(v)){
                merge(u,v);
                cost[++cnt]=t[i].cost;
            }
        }
        sort(cost+1, cost+n);
        reverse(cost+1, cost+n);
        printf("%.2f\n",cost[s]);
    }
    return 0;
}

完全图的最小生成树还是用prim算法好啊。

发布了67 篇原创文章 · 获赞 0 · 访问量 1512

猜你喜欢

转载自blog.csdn.net/qq_44846324/article/details/104562007