zoukankan      html  css  js  c++  java
  • prim算法,克鲁斯卡尔算法---最小生成树

    最小生成树的一个作用,就是求最小花费。要在n个城市之间铺设光缆,主要目标是要使这 n 个城市的任意两个之间都可以通信,但铺设光缆的费用很高,且各个城市之间铺设光缆的费用不同,因此另一个目标是要使铺设光缆的总费用最低。这就需要找到带权的最小生成树

    主要思路:贪心,假设一共有五个点,按道理来讲,应该是先找到图中最小权值的两个点没然后对剩余的点进行遍历。但是也可以任意指定一个点。可以任意指定的原因就是,如果给定的信息可以构成最小生成树的话,那么最小生成树中一定有所有的点,那么这个点也一定在树上,所以可以任意指定一个点进行循环。指定第一个点后,然后寻找其他还没有访问的点到该点的最小距离,找到之后,将该点放入已经访问过的集合中,然后再找剩下的未访问的点到已经访问的这一坨中的点的最小距离,然后不停的循环这个过程,知道所有的点都访问为止。(如果是最大生成树的话,直接改克鲁斯卡尔中的sort就可以了,最小生成树是升序,最大生成树就是降序)

    例题:http://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Index/problemdetail/pid/2144.html

    代码:(Prim)

    #include<iostream>
    #include<cstring>
    #include<string>
    #include<iomanip>
    #include<map>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    # define maxn  1005
    # define inf 0x3f3f3f3f
    int a[maxn][maxn];
    int dis[maxn];
    int n,m;
    int vis[maxn];
    int flag;
    int prime()
    {
        for(int i=1; i<=n; i++)
            dis[i]=a[i][1];//首先把除了1之外的点的距离到1的距离存好
    memset(vis,0,sizeof(vis));//标记数组
    vis[1]=1;
    int temp,k;
    int sum=0;//计算权值和
    for(int i=1; i<n; i++)
    {
        temp=inf;
        for(int j=1; j<=n; j++)
        {
            if(vis[j]==0&&dis[j]<temp)//寻找剩余的点到已经访问过的集合中的距离的最小值
            {
                temp=dis[j];
                k=j;
            }
        }
        if(temp==inf)//如果这个点连不到图上,说明根本无法构成图,直接退出即可
        {
            flag=1;
            break;
        }
        sum+=temp;
        vis[k]=1;//将下一个点标记
        for(int j=1; j<=n; j++)
        {
            if(vis[j]==0&&dis[j]>a[k][j])//dis数组存的不只是剩余的点到k点的最小距离,还应该是剩余的点到已经访问过的点的u最小距离。
            {
                dis[j]=a[k][j];
            }
        }
    }
    return sum;
    }
    int main()
    {
        while(cin>>n>>m)
        {
            memset(a,inf,sizeof(a));//首先对存图的数组进行初始化
            for(int i=1; i<=n; i++)
            {
                a[i][i]=0;
            }//自己到自己的距离是0
            flag=0;
            for(int i=1; i<=m; i++)
            {
                int u,v,w;
                cin>>u>>v>>w;
                if(a[u][v]>w)//防止有重边
                {
                    a[v][u]=a[u][v]=w;
                }
            }
            int t=prime();
            if(m<n-1||flag==1)cout<<0<<endl;//如果,有的点连不到图上,或者给定的信息根本无法构成图,则输出0
            else
            {
                cout<<t<<endl;
            }
        }
        return 0;
    }
    

    克鲁斯卡尔算法:

    #include<iostream>
    #include<iomanip>
    #include<vector>
    #include<map>
    #include<queue>
    #include<stack>
    #include<algorithm>
    using namespace std;
    # define maxn 10000+10
    int n,m;
    struct node
    {
        int x,y,cost;
    } edge[maxn];
    int father[maxn];
    int Find(int t)
    {
        return father[t]==t? t: father[t]=Find(father[t]);
    }
    bool cmp(node t1,node t2){
    return t1.cost<t2.cost;
    }
    int kruskal()
    {
        for(int i=1; i<=n; i++)
        {
            father[i]=i;
        }
        int sum=0;
        sort(edge+1,edge+m+1,cmp);
        for(int i=1; i<=m; i++)
        {
            int t1=Find(edge[i].x);
            int t2=Find(edge[i].y);
            if(t1!=t2)
            {
                sum+=edge[i].cost;
                father[t1]=t2;
            }
        }
        return sum;
    }
    int main()
    {
        while(cin>>n>>m)
        {
            for(int i=1; i<=m; i++)
            {
                cin>>edge[i].x>>edge[i].y>>edge[i].cost;
            }
            int t=kruskal();
            cout<<t<<endl;
        }
        return 0;
    }
    
  • 相关阅读:
    全面监测网站信息
    linux 将Mysql的一张表导出至Excel格式文件
    渗透测试人员发现用户可无限输入密码次数,超过5次未锁定用户,存在暴力破解风险。解放方案:限制每个输入的用户名(不管存不存在该账户)登陆失败次数不超过5次,超过则锁定该用户
    mysql linux下数据库导出 常用操作
    find php.ini 和 php的执行目录 bin目录
    解决:The “https://packagist.laravel-china.org/packages.json” file could not be downloaded
    如何上传代码至GitHub
    7. Jmeter-逻辑控制器介绍与使用
    19、Linux命令对服务器内存进行监控
    20、Linux命令对服务器磁盘进行监控
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10262985.html
Copyright © 2011-2022 走看看