51nod1212无向图最小生成树

1212 无向图最小生成树

基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题

 收藏

 关注

N个点M条边的无向连通图,每条边有一个权值,求该图的最小生成树。

Input

第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)

Output

输出最小生成树的所有边的权值之和。

Input示例

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

Output示例

37prim算法:
#include<stdio.h>
#include<string.h>
#define 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));//全部初值为0表示没有访问过;
    vis[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;}
        }
        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;
    int x,y,w;
    while(~scanf("%d %d",&n,&m)){
        memset(G,inf,sizeof(G));
        while(m--){
            scanf("%d%d%d",&x,&y,&w);
            G[x][y]=G[y][x]=w;
        }
        printf("%d\n",prim(G,n));
    }
}

kruskal算法:

#include <stdio.h>
#include <algorithm>

using namespace std;

#define _min_(a,b) ((a)<(b)?(a):(b))
#define INF 0x3f3f3f3f
#define MAX_N 1005
#define MAX_E 50005

struct edge
{
    int u;
    int v;
    int cost;
};

edge es[MAX_E];

int N,M;
int W[MAX_N][MAX_N];
int mincost[MAX_N];
bool used[MAX_N];

bool cmp(edge e1, edge e2)
{
    return e1.cost < e2.cost;
}

// union-find set
int par[MAX_N];
int rank[MAX_N];
void init_inion_find(int n)
{
    for(int i=0;i<n;i++){
        par[i]=i;
        rank[i]=0;
    }
}
int find(int x)
{
    if(par[x]==x){
        return x;
    }else{
        return par[x]=find(par[x]);
    }
}
void unite(int x,int y)
{
     x=find(x);
     y=find(y);
     if(x==y){
         return;
     }
     if(rank[x]<rank[y]){
         par[x]=y;
     }else{
          par[y]=x;
          if(rank[x]==rank[y]){
              rank[x]++;
          }
     }
}
bool same(int x, int y)
{
     return find(x)==find(y);
}
// end of union-find set

void init()
{
    for(int i=0;i<MAX_N;i++){
        for(int j=0;j<MAX_N;j++){
            W[i][j]=INF;
        }
        mincost[i]=INF;
        used[i]=false;
    }
}

long long kruskal()
{
    long long res=0;
    for(int i=0;i<M;i++){
        edge e=es[i];
        if(!same(e.u, e.v)){
            unite(e.u, e.v);
            res += e.cost;
        }
    }
    return res;
}

int main()
{
    //freopen("18_kruskal.txt","r",stdin);
    init();
    scanf("%d %d",&N,&M);
    for(int i=0;i<M;i++){
        int u,v,cost;
        scanf("%d %d %d",&u,&v,&cost);
        es[i].u = u-1;
        es[i].v = v-1;
        es[i].cost = cost;
    }
    sort(es,es+M,cmp);

    init_inion_find(N);

    long long res = kruskal();
    printf("%lld\n",res);
    return 0;
}
时间: 2024-10-12 04:45:15

51nod1212无向图最小生成树的相关文章

51Nod-1212 无向图最小生成树

51Nod: 1212 无向图最小生成树. link: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1212 1212 无向图最小生成树 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 N个点M条边的无向连通图,每条边有一个权值,求该图的最小生成树. Input 第1行:2个数N,M中间用空格分隔,N为点的数量,M为边的数量.(2 <= N <= 1000, 1 <= M <

51nod1212 无向图最小生成树(Prim)

题目描述: N个点M条边的有向连通图,每条边有一个权值,求该图的最小生成树. Input 第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) OutPut 输出最小生成树的所有边的权值之和. Input示例 9 14 1 2 4 2 3 

1212 无向图最小生成树

1212 无向图最小生成树 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 N个点M条边的无向连通图,每条边有一个权值,求该图的最小生成树. Input 第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 <= 10

所有边权均不相同的无向图最小生成树是唯一的证明

设G是所有边权均不相同的无向联通图. 证明一: 首先,易证图G中权值最小的边一定是最小生成树中的边.(否则最小生成树加上权值最小的边后构成一个环,去掉环中任意一条非此边则形成了另一个权值更小的生成树). 之后用反证法,假设G存在俩个不同的最小生成树 ①.设G的俩个不同的最小生成树T1 T2,设这俩颗生成树的并集为子图G1,G1为连通图且T1 T2显然为G1的最小生成树,由首先可得知俩颗生成树至少包含一条公共边,将G1中两颗生成树的公共边删去,得到子图G2.G2由一个或多个连通分量组成,其中至少有

无向图最小生成树Kruskal算法

问题 最小生成树的Kruskal算法 描述:有A.B.C.D四个点,每两个点之间的距离(无方向)是(第一个数字是两点之间距离,后面两个字母代表两个点):(1,'A','B'),(5,'A','C'),(3,'A','D'),(4,'B','C'),(2,'B','D'),(1,'C','D') 生成边长和最小的树,也就是找出一种连接方法,将各点连接起来,并且各点之间的距离和最小. 思路说明: Kruskal算法是经典的无向图最小生成树解决方法.此处列举两种python的实现方法.这两种方法均参考

无向图最小生成树Prim算法

问题 无向图最小生成树的Prim算法.一般的实现过程,采用了常规排序.本文在用Python实现中,使用了python的堆排序模块,不仅精简代码,而且提高效率. 思路说明 假设点A,B,C,D,E,F,两点之间有连线的,以及它们的距离分别是:(A-B:7);(A-D:5);(B-C:8);(B-D:9);(B-E:7);(C-E:5);(D-E:15);(D-F:6);(E-F:8);(E-G:9);(F-G:11) 关于Prim算法的计算过程,参与维基百科的词条:[普里姆算法] 将上述点与点关系

51Nod 1212无向图最小生成树

prim #include<stdio.h> #include<string.h> #define 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));//全部初值为0表示没有访问过: vis[1]=1; for(i=2;i<=n;i++) lowc[i

图论 - 无向图最小生成树

N个点M条边的无向连通图,每条边有一个权值,求该图的最小生成树. Input 第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) Output 输出最小生成树的所有边的权值之和. Input示例 9 14 1 2 4 2 3 8 3 4 

hihocoder(1097) 最小生成树Prim

图论一直是自己算法中最最最柔弱的部分,主要是,当年数据结构的课程,后面就去打酱油了,后来时间又都花在了电赛上,平时用的相关部又少,这一部分就更弱了,总是懒得捡起来,但是现在可是没退路了,开始好好复习这一部分. Prim算法是求解无向图最小生成树的经典算法,和Dijkstra算法类似,但是Prim算法每次获取一个新的顶点后,都有一个聚合的过程,而Dijkstra没有,并且Dijkstra的对象是有向图的单源最短路径,所以这两个算法起始本质上是不同的,然而他们的思想是一致的:贪心 刚好借着hihoc