最小生成树

最小生成树
Description
在一张图上有N个点,点与点之间的连接的花费都已经告诉你了,请你设计一下,如何解决这个“最小生成树”的问题。要求用prim方法求解。

Input
首先输入一个数字N(0〈=N〈=100)
然后输入一个N*N的矩阵 其中第i行第j列的数字k表示从点i到点j需要的花费。

Output
一个数字,最少需要多少花费才能使得整张图任意两点都直接或者间接连通(也就是最小生成树的权)

Sample Input
5
0 41 67 34 0
41 0 69 24 78
67 69 0 58 62
34 24 58 0 64
0 78 62 64 0

0

2
0 1
1 0
Sample Output
116
0
1

#include<bits/stdc++.h>
using namespace std;
struct jg{
    int x,y,q;
};
#define INF 999999999
int G[101][101];
bool bj1[101],bj2[101];
jg nsj(int xn);
int main()
{
    int n,ans,c;
    jg pp;
    while(cin>>n)
    {
        if(n==0)
        {
            cout<<0<<endl;
        }
        else
        {
            memset(bj1,false,sizeof(bj1));
            memset(bj2,true,sizeof(bj2));
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    cin>>G[i][j];
                }
            }
            ans=0;
            c=1;
            bj1[1]=true;
            bj2[1]=false;
            while(c<n)
            {
                pp=nsj(n);
                ans+=pp.q;
                bj1[pp.y]=true;
                bj2[pp.y]=false;
                c++;
            }
            cout<<ans<<endl;
        }
    }
    return 0;
}
jg nsj(int xn)
{
    jg nsjj;
    int mi,i,j;
    mi=999999999;
    nsjj.x=1;
    nsjj.y=1;
    for(i=1;i<=xn;i++)
    {
        if(bj1[i])
        {
            for(j=1;j<=xn;j++)
            {
                if(bj2[j])
                {
                    if(mi>G[i][j])
                    {
                        mi=G[i][j];
                        nsjj.x=i;
                        nsjj.y=j;
                        nsjj.q=mi;
                    }
                }
            }
        }
    }
    return nsjj;
}

最小生成树(要求用kruskal算法写)
Description
在一张图上有N个点,点与点之间的连接的花费都已经告诉你了,请你设计一下,如果解决这个“最小生成树”的问题。

Input
首先输入一个数字N(0〈=N〈=100)
然后输入一个N*N的矩阵 其中第i行第j列的数字k表示从点i到点j需要的花费。

Output
一个数字,最少需要多少花费才能使得整张图任意两点都直接或者间接连通(也就是最小生成树的权)

Sample Input
5
0 41 67 34 0
41 0 69 24 78
67 69 0 58 62
34 24 58 0 64
0 78 62 64 0

0

2
0 1
1 0
Sample Output
116
0
1

#include<bits/stdc++.h>
using namespace std;
struct jg{
    int x,y,q;
};
jg a[5003];
int zz[101];
int n,e;
void Merge(int r,int t);
bool bj(const jg &u,const jg &v);
int main()
{
    int ans,xx,aa,b,alg,k,i,j;
    while(cin>>n)
    {
        for(int i=1;i<=n;i++)
        {
            zz[i]=i;
        }
        e=0;
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
            {
                cin>>xx;
                if(i<j)
                {
                    e++;
                    a[e].x=i;
                    a[e].y=j;
                    a[e].q=xx;
                }
            }
        }
        sort(a+1,a+e+1,bj);
        ans=0;
        k=n;
        alg=1;
        while(k>1)
        {
            aa=zz[a[alg].x];
            b=zz[a[alg].y];
            if(aa!=b)
            {
                ans+=a[alg].q;
                Merge(aa,b);
                k--;
            }
            alg++;
        }
        cout<<ans<<endl;
    }
    return 0;
}
void Merge(int r,int t)
{
    int i;
    for(i=1;i<=n;i++)
    {
        if(zz[i]==t)
        {
            zz[i]=r;
        }
    }
}
bool bj(const jg &u,const jg &v)
{
    return u.q<v.q;
}

不同条件下的最小生成树
Description
课堂上我们学习了最小生成树的算法思想,也在实验课自己动手实现了这个算法,今天我们仍然要求来实现这个算法,只不过输入要求不一样,而且给定的图也不是所有顶点之间都有连接的边,有些顶点之间没有边,要求计算的最小费用也有点变化,请准确理解并求解.

Input
输入的第一行是测试数据的组数,对于每一组测试数据,有两部分,第一部分只有一行,分别有两个正整数nNode、nEdge(分别表示图的顶点数、边数,其中顶点编号为1到nNode,1<=nNode<=100);第二部分共有nEdge行,每行有四个正整数nFrom、nTo、nDist、nV(分别表示这一条边的起始顶点、终止顶点、边的长度、这条边上能够承载的速度,当然它们的单位已经换算成相应的标准单位了,你不用考虑单位换算的问题;其中1<=nFrom,nTo<=nNode)。输入数据保证能够有生成树,每条边在计算费用时假设是各自的匀速运动。

Output
你的任务是以每条边上能承载的速度前提下将所需时间作为边的费用,求出最小生成树的花费,输出只有一行,即所求的花费,输出时保留一位小数。

Sample Input
1
6 10
1 2 6 3
1 3 1 1
1 4 5 2
2 3 5 3
2 5 3 2
3 4 5 3
3 5 6 3
3 6 4 2
4 6 2 1
5 6 6 3
Sample Output
7.8

#include<bits/stdc++.h>
using namespace std;
struct jg{
    int x,y,q,v;
};
jg a[5003];
int zz[101];
int n,e;
void Merge(int r,int t);
bool bj(const jg &u,const jg &x);
int main()
{
    int aa,b,alg,k,i,j,jpii,kk;
    double ans;
    cin>>jpii;
    for(kk=1;kk<=jpii;kk++)
    {
        cin>>n>>e;
        for(i=1;i<=n;i++)
        {
            zz[i]=i;
        }
        for(i=1;i<=e;i++)
        {
            cin>>a[i].x>>a[i].y>>a[i].q>>a[i].v;
        }
        sort(a+1,a+e+1,bj);
        ans=0.0;
        k=n;
        alg=1;
        while(k>1)
        {
            aa=zz[a[alg].x];
            b=zz[a[alg].y];
            if(aa!=b)
            {
                ans+=(1.0*a[alg].q)/(1.0*a[alg].v);
                Merge(aa,b);
                k--;
            }
            alg++;
        }
        printf("%.1lf\n",ans);
    }
    return 0;
}
void Merge(int r,int t)
{
    int i;
    for(i=1;i<=e;i++)
    {
        if(zz[i]==t)
        {
            zz[i]=r;
        }
    }
}
bool bj(const jg &u,const jg &x)
{
    return (1.0*u.q)/(1.0*u.v)<(1.0*x.q)/(1.0*x.v);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值