zoukankan      html  css  js  c++  java
  • Hdu1233 最小生成树的一些笔记

    1/一棵树的任意两个节点都有路径

    2/任何两个顶点之间都有边(弧)相连称为完全图
    完全图有n个节点时,总共有n*(n-1)/2条边

    3/生成树只能有n-1条边

    prim的实现:

    起始点start

    u=start;
    do{
      将u的所有相连的边储存到一个最小堆中

      while(堆非空)
        利用最小堆性质弹出最小权值的边(这些边的起始点u一定visited)
        此边的顶点分别是u和v
        判断点v是否visited
        若是则重新在堆中查找
        若否则将该边保存至MST中,break结束;
    }while(MST中边数达到N-1)

    prim的实现2://严蔚敏数据结构:

    MST中的点集为U
    主要思想是每次都从V-U到U的边中找到权值最小的边
    找到该边时将该边在V-U中的顶点转移到U中

    具体实现是:
    利用一个closedge[]数组,closedge[i].lowcost表示V-U中的点i到U的最小权值
    如果只是求最小生成树的权值和的话,直接创建lowcost[]数组更好

    lowcost[]数组实际上运用了一个窍门
    若点v到u0的lowcost[v]=1
    当u1加入U之后
    若v到u1有边,且权值比lowcost[v]小
    则lowcost[v]=w(u1,v)
    总之,lowcost[]总能找到U到V-U中最小权值的边

    将V-U中的点移至U中的方法是利用visited[]数组标记,visited[U]=1,visited[V-U]=0
    U==V时,辅助变量cnt==n

    while(U!=V){
      for U中的点u
        for V-U中的点v
          若(u,v)的权值w(u,v)小于closedge[v].lowcost)
          closedge[v].lowcost=w(u,v)
          若w(u,v)<min
            min=w(u,v)

    }

    kruskal的实现:

    将所有边都放进最小堆中

    while(MST中边数为N-1)
      从最小堆中弹出最小权值边
      该边的两个顶点u,v,可利用并查集找出u与v的根
      若u的根与v的根相同,则说明u与v在同一连通分量中,此时,添加此边会在MST中形成环,故将该边舍弃
      若不同,则将此边加入MST中

     

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1233

    贴上Prim代码:

    #include<iostream>
    #include<cstring>
    #include<cmath>
    #define INF 9999999
    using namespace std;
    
    int graph[100][100];
    int lowcost[100];
    int n;
    bool vis[100];
    int Min,sum,cur;
    
    int prim(){
        cur=1;
        sum=0;
        vis[1]=1;
    
        for(int cnt=1;cnt<n;cnt++){                     //n-1´Î
    
            for(int i=1;i<=n;i++)
                if(!vis[i] && graph[cur][i]<lowcost[i])
                    lowcost[i]=graph[cur][i];
    
            Min=INF;                                    
            for(int i=1;i<=n;i++)
            {
                if(!vis[i] && lowcost[i]<Min){
                    Min=lowcost[i];
                    cur=i;
                }
            }
            vis[cur]=1;
            sum+=Min;
        }    
        return sum;
    }
    
    int main (){
    
        while(cin>>n){ 
            if(!n)
                break;
    
            int u,v,w;
            memset(graph,INF,sizeof(graph));           
            memset(vis,0,sizeof(vis));
            memset(lowcost,INF,sizeof(lowcost));
            for(int i=0;i<n*(n-1)/2;i++){
                cin>>u>>v>>w;
                graph[u][v]=w;
                graph[v][u]=w;
            }
    
            cout<prim()<<endl;
        }
        return 0;
    }
    View Code

    贴上Kruskal代码

    //并查集的实现
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    
    const int maxn=100;
    int parent[maxn];
    int Rank[maxn];
    int n;//集元素的个数 
    
    struct edgenode{
        int u,v,w;
    };
    
    int find(int x){
        while(parent[x]!=x)
            x=parent[x];
        return x;
    }
    
    void Union(int x,int y){
    
        //x=find(x);
        //y=find(y);
        if(Rank[x]==Rank[y])    //同秩的时候,令y成为x的父节点 
        {
            Rank[y]++;
            parent[x]=y;
        } 
        else if(Rank[x]>Rank[y])
            parent[y]=x;
        else
            parent[x]=y;
    
    }   //加权规则 
    
    void makeSet(){
        for(int i=1;i<=n;i++)
        {
            Rank[i]=0;
            parent[i]=i;
        }
    }
    
    bool cmp (edgenode& ed1,edgenode& ed2)
    {
        return ed1.w<ed2.w;
    }
    
    edgenode edge[maxn*maxn/2];
    int sum;
    int x,y,k;
    
    int kruskal(){
    
        sum=0;
        sort(edge,edge+k,cmp);      
        for(int i=0;i<k;i++){  
            x=find(edge[i].u);
            y=find(edge[i].v);
            if(x!=y){
                parent[x]=y;
                sum+=edge[i].w;      
            }
        }
        return sum;
    }
    
    int main (){
    
        while(cin>>n&&n)
        {    
    
            k=n*(n-1)/2;    //边数k
            for(int i=0;i<k;i++) 
                cin>>edge[i].u>>edge[i].v>>edge[i].w;
    
            makeSet();
            cout<<kruskal()<<endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Delphi 农历算法
    Installing Custom Maps for L4D
    双网卡,上网走外网网卡,内网走内网网卡设置
    L4D的指令合集
    两个RGB的颜色半透明混色算法
    中国省级行政区划变动情况
    Win7编程:在按钮中加入管理员权限运行
    教你快速识别手机质量的好坏
    如何利用预编译指令来判断Delphi 的版本?
    在.NET中读写INI文件 ——兼谈正则表达式的应用
  • 原文地址:https://www.cnblogs.com/neverchanje/p/3538453.html
Copyright © 2011-2022 走看看