最小生成树模板题POJ - 1287-prim+kruskal

POJ - 1287超级模板题

大概意思就是点的编号从1到N,会给你m条边,可能两个点之间有多条边这种情况,求最小生成树总长度?

这题就不解释了,总结就算,prim是类似dijkstra,从第一个点出发,每次走这个点没走过的最小边权值,这样不断找下去就可以找出,本质就是贪心算法

而kruskal是利用并查集,先按照边权值大小排序,然后从小的边开始往里面添加边,利用并查集判断是否在一个联通分量里面(就是是否相连)如果不相

连就建立边,从而建图,注意,节点编号如果是从1->n,那么相应初始化就应该从1->N;

prim版本:

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 using namespace std;
 5 const int INF = 0x3f3f3f3f;
 6 const int maxx = 1e2+7;
 7 int cost[maxx][maxx];
 8 int mincost[maxx];
 9 bool used[maxx];
10 int v;
11 int m,n;
12 int prim(){
13   for (int i=1;i<=n;i++){
14     mincost[i]=INF;
15     used[i]=false;
16   }
17  mincost[1]=0;//这里的数组的编号,代表我最开始建图的点
18   int res=0;
19   while(true){
20     int v = -1;
21     for (int u=1;u<=n;u++){ //枚举边找到这个点的下一个边权值最小的点
22         if (!used[u] && (v==-1 || mincost[u] < mincost[v])) v=u;
23     }
24     if (v == -1)break;//没有的话就返回,无法建图
25     used[v]=true;//顶点加入
26     res+=mincost[v];
27     for (int u=1;u<=n;u++){
28         mincost[u] = min(mincost[u],cost[v][u]);//???
29     }
30   }
31   return res;
32 }
33 int main(){
34   int tmp1,tmp2,tmp3;
35    while(scanf("%d",&n) && n){
36       scanf("%d",&m);
37       if (m==0){
38         cout<<"0"<<endl;
39         continue;
40       }
41      for (int i=1;i<=n;i++){
42         for(int j=1;j<=n;j++){
43             if (i==j)cost[i][j]=0;
44             else cost[i][j]=INF;
45         }
46      }
47      for (int i=1;i<=m;i++){
48         scanf("%d%d%d",&tmp1,&tmp2,&tmp3);
49         if (tmp3<cost[tmp1][tmp2])cost[tmp1][tmp2]=cost[tmp2][tmp1]=tmp3;//更新成最短边
50      }
51     cout<<prim()<<endl;
52    }
53   return 0;
54 }

Kruskal

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
using namespace std;
struct node{
  int u,v,w;
}a[10050];
int p[10055];
int r[10055];
int n,m;
int find(int x){return p[x] == x ? x : p[x] = find(p[x]);}//找根节点
int cmp(node x,node y)
{
    return x.w<y.w;//按照边权值排序
}
int Kruskal(){
        int ans=0;
        int num=0;
        for (int i=1; i<=n; i++)p[i]=i;
        sort(a+1,a+1+m,cmp);
        for (int i=1; i<=m; i++)
        {
            int x=find(a[i].u);//出发点的根节点
            int y=find(a[i].v);//到达点的根节点
            if (x!=y)//不是一个根节点
            {
                ans+=a[i].w;//连接
                p[x]=y;//y是x的父亲节点
                num++;//建立好了n-1条边
            }
            if (num==n-1){
                break;
            }
        }
    return ans;
}
int main()
{
    int tmp1,tmp2,tmp3;
    while(~scanf("%d",&n))
    {
        if (n==0)break;
        scanf("%d",&m);
        for (int i=1; i<=m; i++)
        {
            scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
        }
        printf("%d\n",Kruskal());
    }
    return 0;
}

原文地址:https://www.cnblogs.com/bluefly-hrbust/p/9410730.html

时间: 2024-10-11 00:11:12

最小生成树模板题POJ - 1287-prim+kruskal的相关文章

还是畅通工程——最小生成树模板题

题目链接 题意: 给定n个村庄,m=(n*(n-1)/2)条关系  u,v,w 表示  u到 v之间的距离是 w 题解: 裸最小生成树模板题 代码: #include<iostream> #include<stdio.h> #include<math.h> #include<algorithm> #include<vector> using namespace std; typedef long long ll; const int maxn =

字典树模板题 POJ 2503

1 #include <cstdio> 2 #include <cstring> 3 4 char en[11],fr[11]; 5 int st; 6 struct Tire{ 7 int next[26]; 8 char eng[11]; 9 }node[200005]; 10 void insert(char *s,int cur) 11 { 12 if(*s){ 13 if(!node[cur].next[*s-'a']) 14 node[cur].next[*s-'a']

POJ2560 (最小生成树模板题)

In an episode of the Dick Van Dyke show, little Richie connects the freckles on his Dad's back to form a picture of the Liberty Bell. Alas, one of the freckles turns out to be a scar, so his Ripley's engagement falls through. Consider Dick's back to

(heu step 6.1.1)Constructing Roads(最小生成树模板题:求让n个点连通的最小费用)

题目: Constructing Roads Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 207 Accepted Submission(s): 135   Problem Description There are N villages, which are numbered from 1 to N, and you should bu

最小生成树算法详解(prim+kruskal)

最小生成树概念: 一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边. 最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里姆)算法求出.最小生成树其实是最小权重生成树的简称. prim: 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (graph theory)),且其所有边的权值之和亦为最小. p

RMQ 模板题 poj 3264

题目:点这里 题意:给一个长度n的数列,然后又Q个询问,问L   到R   中最大值与最小值的差. 分析:RMQ 的模板题. 代码: #include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> using namespace std; const int max_=50005; int minm,maxm; int dp_max[max_][20],dp_min[ma

HDU 1233 prim kruskal最小生成树模板题

A - 还是畅通工程 Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description 某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离.省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小.请计算最小的公路总长度. Input 测试输入包含若干测试

POJ 1287 Networking (最小生成树模板题)

Description You are assigned to design network connections between certain points in a wide area. You are given a set of points in the area, and a set of possible routes for the cables that may connect pairs of points. For each possible route between

poj 1251 最小生成树模板题

Sample Input 9 //n 结点数A 2 B 12 I 25B 3 C 10 H 40 I 8C 2 D 18 G 55D 1 E 44E 2 F 60 G 38F 0G 1 H 35H 1 I 353A 2 B 10 C 40B 1 C 200Sample Output 21630 prim算法 1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <