zoukankan      html  css  js  c++  java
  • Prim算法---最小生成树

    最小生成树的Prim算法也是贪心算法的一大经典应用。Prim算法的特点是时刻维护一棵树,算法不断加边,加的过程始终是一棵树。

    Prim算法过程:

    一条边一条边地加, 维护一棵树。

    初始 E = {}空集合, V = {任意节点}

    循环(n – 1)次,每次选择一条边(v1,v2), 满足:v1属于V , v2不属于V。且(v1,v2)权值最小。

    E = E + (v1,v2)
    V = V + v2

    最终E中的边是一棵最小生成树, V包含了全部节点。
    以下图为例介绍Prim算法的执行过程。
    Prim算法的过程从A开始 V = {A}, E = {}

    选中边AF , V = {A, F}, E = {(A,F)} 

    选中边FB, V = {A, F, B}, E = {(A,F), (F,B)}

    选中边BD, V = {A, B, F, D},   E = {(A,F), (F,B), (B,D)}

    选中边DE, V = {A, B, F, D, E},   E = {(A,F), (F,B), (B,D), (D,E)}
     
    选中边BC, V = {A, B, F, D, E, c},   E = {(A,F), (F,B), (B,D), (D,E), (B,C)}, 算法结束。
    最后,我们来提供输入输出数据,由你来写一段程序,实现这个算法,只有写出了正确的程序,才能继续后面的课程。
     
    输入

    第1行:2个数N,M中间用空格分隔,N为点的数量,M为边的数量。(2 <= N <= 1000, 1 <= M <= 50000)
    第2 - M + 1行:每行3个数S E W,分别表示M条边的2个顶点及权值。(1 <= S, E <= N,1 <= W <= 10000)
    输出
     
    输出最小生成树的所有边的权值之和。
     
    输入示例

    9 14
    1 2 4
    2 3 8
    3 4 7
    4 5 9
    5 6 10
    6 7 2
    7 8 1
    8 9 7
    2 8 11
    3 9 2
    7 9 6
    3 6 4
    4 6 14
    1 8 8

    输出示例

    37
     
    请选取你熟悉的语言,并在下面的代码框中完成你的程序,注意数据范围,最终结果会造成Int32溢出,这样会输出错误的答案。
    不同语言如何处理输入输出,请查看下面的语言说明。
     
     
    简单的最小生成树,自己写的代码一直过不了
     
    AC代码(prim算法)
    #include<iostream>  
    #include<cstdio>  
    #include<map>  
    #include<cstring>  
    #include<string>  
    #include<algorithm>  
    #include<queue>  
    #include<vector>  
    #include<stack>  
    #include<cstdlib>  
    #include<cctype>  
    #include<cstring>  
    #include<cmath>  
    using namespace std;  
    const int inf=0x3f3f3f3f;  
    int G[1001][1001];//邻接矩阵  
    int vis[1001],lowc[1001];  
    int prim(int G[][1001],int n){  
        int i,j,p,minc,res=0;  
        memset(vis,0,sizeof(vis));  
        vis[1]=1;//从1开始访问  
        for(i=2;i<=n;i++) lowc[i]=G[1][i];  
        for(i=2;i<=n;i++){  
            minc=inf; p=-1;  
            for(j=1;j<=n;j++){  
                if(vis[j]==0&&lowc[j]<minc){  
                    minc=lowc[j]; p=j;  
                }  
            }  
            //cout<<minc<<endl;  
            if(inf==minc) return -1;//原图不联通  
            res+=minc; vis[p]=1;  
            for(j=1;j<=n;j++){//更新lowc[]  
                if(vis[j]==0&&lowc[j]>G[p][j]){  
                    lowc[j]=G[p][j];  
                }  
            }  
        }  
        return res;  
    }  
      
    int main()  
    {  
        int n,m;  
        while(cin>>n>>m){  
            int x,y,w;  
            memset(G,inf,sizeof(G));//首先记录所有边的权为inf  
            for(int i=1;i<=m;i++){  
                cin>>x>>y>>w;  
                G[x][y]=G[y][x]=w;  
                //cout<<G[x][y]<<endl;  
            }  
            //int res=prim(n);  
            cout<<prim(G,n)<<endl;  
        }  
        return 0;  
    }  
    

      

    自己写的代码不知道错哪了(kruskal算法)
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    
    using namespace std;
    
    struct tr
    {
    	int s,e,w;
    }p[50000+10];
    
    bool cmp(tr x, tr y)
    {
    	return x.w < y.w;
    }
    
    int n,m;
    int f[1000+10];
    int i,j;
    long long ans;
    
    int find(int x)  //找父亲 
    {  
    	int r = x;
    	while(f[r] != r)
    	r = f[r];
    	return r;
    	int i = x, j;
    	while(i != r)
    	{
    		j = f[i];
    		f[i] = r;
    		r = j;
    	}   
    } 
    
    void join(int x, int y)
    {
    	int fx = find(x);
    	int fy = find(y);
    	if(fx != fy)
    		f[fx] = fy;
    } 
    
    int kruskal()
    {
    	sort(p, p+m, cmp);
    	for(i=0; i<n; i++)
    	{
    		f[i] == i;//初始化 父亲节点 
    	}
    	for(i=0; i<n; i++)
    	{
    		if(find(p[i].s) != find(p[i].e))
    		{
    			join(p[i].e, p[i].s);
    			ans += p[i].w;
    		}
    	}
    	return ans;
    }
    
    int main()
    {
    	ans=0;
    	scanf("%d %d",&n,&m);
    	for(i=0; i<m; i++)
    	{
    		scanf("%d %d %d",&p[i].s, &p[i].e, &p[i].w);
    	}
    	kruskal();
    	printf("%lld
    ",ans);
    	return 0;
     } 
    

      

     
     
    永远渴望,大智若愚(stay hungry, stay foolish)
  • 相关阅读:
    20.multi_case04
    Linux 性能监测:Memory
    Linux 性能监测:介绍
    Linux 性能监测:CPU
    服务器压力上不去原因分析
    Oracle数据库shutdown immediate被hang住的几个原因
    性能测试需求指标分析方法
    关于spotlight for Windows和spotlight for oracle的使用
    Oracle性能监控脚本(sql)
    Oracle 常用性能监控SQL语句
  • 原文地址:https://www.cnblogs.com/h-hkai/p/7467202.html
Copyright © 2011-2022 走看看