zoukankan      html  css  js  c++  java
  • hdoj-1233-还是畅通工程

    题目:hdoj-1233

    题解:

    本题是典型的最小生成树问题,给出的是无向图,这里使用的方法是Prim最小生成树算法。

    Reference

    Prim算法参照:最小生成树-Prim算法和Kruskal算法,讲的很详细了。

    测试的时候可以参考这幅图:

    算法介绍:

    主要步骤(摘自上文链接):

    1).输入:一个加权连通图,其中顶点集合为V,边集合为E;

    2).初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {},为空;

    3).重复下列操作,直到Vnew = V:

    a.在集合E中选取权值最小的边<u, v>,其中u为集合Vnew中的元素,而v不在Vnew集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);

    b.将v加入集合Vnew中,将<u, v>边加入集合Enew中;

    4).输出:使用集合Vnew和Enew来描述所得到的最小生成树。

    本题维护两个数组:
    (1)Primgh二维数组,存储图。
    (2)refer数组,判断一个节点是否在Vnew中。

    用于存边的数组Enew在本题中不需要。

    代码:

    //
    //  main.cpp
    //  Prim_1233
    //
    //  Created by wasdns on 16/11/24.
    //  Copyright © 2016年 wasdns. All rights reserved.
    //
    
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <algorithm>
    #include <string>
    #include <string.h>
    #define maxn 10000005;
    using namespace std;
    
    int Primgh[10000][10000];                        //存储图
    
    bool refer[10005];                               //判断是否在Enew中
    
    /*
        用于初始化的函数
     */
    
    void Initial(int n, int m)
    {
        int i, j;
        
        for (i = 1; i <= n; i++)
        {
            refer[i] = false;
            
            for (j = 1; j <= n; j++)
            {
                if (i == j) {
                    Primgh[i][j] = 0;
                }
                
                else Primgh[i][j] = maxn;
            }
        }
        
        int u, v, w;
        
        for (i = 1; i <= m; i++)
        {
            cin >> u >> v >> w;
            
            Primgh[u][v] = w;
            Primgh[v][u] = w;
        }
    }
    
    /*
        Prim算法,主体部分
     */
    
    int Prim_Alg(int n, int m)
    {
        Initial(n, m);
        
        int i, j, k;
        
        int ans = 0;                
        //最小生成树的路径长度                 
        
        refer[1] = true;            
        //选择点1出发        
        
        //最小生成树一共有n-1条边,因此需要寻找最短边n-1次,基于贪心
        for (i = 1; i <= n-1; i++)  
        {
            int minlen = maxn;      
            //minlen: 在Vnew中的节点所连接的边中,寻找cost最小的边
            
            int rcd = 1;            
            //cost最小的边有两个节点,rcd记录其中的不属于Vnew的节点
            
            for (j = 1; j <= n; j++)        
            {
                if (!refer[j]) continue;    
                //遍历Vnew中的所有节点
                
                int len1 = maxn;            
                //对于Vnew中的某个节点来说,所连接的最短的路径cost大小
                
                int rcd1 = 1;               
                //对于Vnew中的某个节点来说,rcd记录的节点
                
                //贪心,寻找这个节点连接的cost最小的路径
                for (k = 1; k <= n; k++)    
                {
                    if (!refer[k])
                    {
                        if (Primgh[j][k] < len1) {
                            
                            len1 = Primgh[j][k];
                            
                            rcd1 = k;
                        }
                    }
                }
                
                if (len1 < minlen) {        
                    //判断贪心得到的路径是否是全局cost最短
                    
                    minlen = len1;
                    
                    rcd = rcd1;
                }
            }
            
            /*Debug:*/
            //char check = 'A'+rcd-1;
            //cout << "rcd: " << check << endl;
            //cout << "minlen: " << minlen << endl;
            
            refer[rcd] = true;              
            //贪心求出cost最小的路径,rcd记录的节点入Vnew
            rcd = 1;                        
            //重置rcd
            
            ans += minlen;                  
        }
        
        return ans;
    }
    
    int main()
    {
        int n, m;
        
        while (scanf("%d", &n) != EOF)
        {
            if (n == 0) break;
            
            m = n * (n-1) / 2;
            
            cout << Prim_Alg(n, m) << endl;
        }
        
        return 0;
    }
    
    
    

    2016/11/24

  • 相关阅读:
    鸿合爱学班班.kl课件转ppt课件
    Mac下Android Studio添加忽略文件的方法
    Android中处理PPI
    Mac下配置全局gradlew命令
    Application启动图
    图像合成模式XferMode
    path绘制
    drawArc 画扇形 画弧线
    okhttp请求完整流程图
    责任链模式
  • 原文地址:https://www.cnblogs.com/qq952693358/p/6099107.html
Copyright © 2011-2022 走看看