• 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;
    }
    
  • 相关阅读:
    官方示例之地球模块十:拔高GeoPolygon
    全景虚拟漫游技术实现(three.js vs ThingJS) Javascript 3D开发 前端 物联网 webgl 三维建模 3D模型 虚拟 全景
    一个3D城市地图应用工具,等你获取 3D 全景 可视化
    H5动画优化之路
    CSS3实现气泡效果
    清除浮动方法总结
    静态页面参数传递&回调函数写法&快速排序的实现方法
    使用SeaJS实现模块化JavaScript开发(新)
    《无懈可击的Web设计》_灵活的文字
    深入探究JavaScript中的比较问题
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10262985.html
Copyright © 2020-2023  润新知