hihocoder1097最小生成树(prim算法)

prim算法描述:

prim算法的思想和代码都跟dijkstra算法非常相似。

在dijkstra算法中,我们用每次取出未标记集合中到源点最近的点进行标记并更新其邻接点到源点的距离:当d[x]+w<d[y]时更新d[y]=d[x]+w。

而在prim算法中,我们只需要对dijkstra算法稍作改动即可,即只需要改变一下更新操作:当w<d[y]时更新d[y]=w,此时d[y]的含义是节点y连接到最小生成树的边的最小取值。也就是说,从图中某个节点发出了边可能有若干条,而最终将该节点连接到最小生成树上的那条必定是这些边中最短的。可以用反证法证明如下:如果从节点u发出的边中最短的边为(u, v),我们假设将节点u连接到最小生成树上的边不是(u, v)而是其他的某条边,设在最小生成树上u到v的最短路径为u--p1--p2--...--pk--v,假设我们现在将边(u, p1)去掉,然后将边(u, v)连接起来,显然,这仍然是一棵生成树,且(u, v)这条边比(u, p1)这条边更短,因此我们现在这棵生成树比之前那棵生成树上所有边的权重和更小,这与我们最初的假设矛盾,所以最初的假设不成立,故原命题得证。最终,最小生成树的边权和为d数组所有元素之和。

我的代码如下:

 1 #include <iostream>
 2 #include <set>
 3 #include <cstring>
 4
 5 using namespace std;
 6
 7 #define MAXN 1005
 8 #define INF 0x7fffffff
 9
10 int w[MAXN][MAXN], n, d[MAXN];
11 bool onTree[MAXN];
12
13 struct comp
14 {
15     bool operator()(const int &a, const int &b)const
16     {
17         if(d[a]==d[b]) return a<b;
18         return d[a]<d[b];
19     }
20 };
21
22 void prim()
23 {
24     for(int i=1; i<=n; ++i) d[i] = INF;
25     d[1] = 0;
26     memset(onTree+1, 0, n);
27     set<int, comp> st;
28     for(int i=1; i<=n; ++i) st.insert(i);
29     while(!st.empty())
30     {
31         int x = *st.begin();
32         st.erase(x);
33         onTree[x] = true;
34         for(int y=1; y<=n; ++y)
35         {
36             if(y!=x&&!onTree[y]&&w[x][y]<d[y])
37             {
38                 st.erase(y);
39                 d[y] = w[x][y];
40                 st.insert(y);
41             }
42         }
43     }
44 }
45
46 int main()
47 {
48     while(cin>>n)
49     {
50         for(int i=1; i<=n; ++i) for(int j=1; j<=n; ++j) cin>>w[i][j];
51         prim();
52         int ans = 0;
53         for(int i=1; i<=n; ++i) ans += d[i];
54         cout<<ans<<endl;
55     }
56     return 0;
57 }
时间: 2024-10-06 16:55:48

hihocoder1097最小生成树(prim算法)的相关文章

最小生成树--prim算法

一个无向图G的最小生成树就是由该图的那些连接G的所有顶点的边构成的树,且其总价值最低,因此,最小生成树存在的充分必要条件为图G是连通的,简单点说如下: 1.树的定义:有n个顶点和n-1条边,没有回路的称为树 生成树的定义:生成树就是包含全部顶点,n-1(n为顶点数)条边都在图里就是生成树 最小:指的是这些边加起来的权重之和最小 2.判定条件:向生成树中任加一条边都一定构成回路 充分必要条件:最小生成树存在那么图一定是连通的,反过来,图是连通的则最小生成树一定存在 上图的红色的边加上顶点就是原图的

hdu 3371 最小生成树prim算法

Connect the Cities Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 8992    Accepted Submission(s): 2519 Problem Description In 2100, since the sea level rise, most of the cities disappear. Thoug

POJ1258最小生成树(prim算法)

POJ1258 思路:首先把第一个结点加入树中,每次往树中加入一个结点,加入的结点必须是与当前树中的结点距离最小那个点,这样每次把结点加入树中选取的都是最小权值,循环n-1次后把所有结点都加入树中. #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int MAXN = 1e9; //创建map二维数组储存图表,low数组记录每2个点间最小权值,vis数组标记

poj1789Truck History(最小生成树prim算法)

题目链接: 啊哈哈,点我点我 思路:根据字符串中不同的长度建图,然后求图的最小生成树.. 题目: Truck History Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 18272   Accepted: 7070 Description Advanced Cargo Movement, Ltd. uses trucks of different types. Some trucks are used for vege

数据结构:最小生成树--Prim算法

最小生成树:Prim算法 最小生成树 给定一无向带权图,顶点数是n,要使图连通只需n-1条边,若这n-1条边的权值和最小,则称有这n个顶点和n-1条边构成了图的最小生成树(minimum-cost spanning tree). Prim算法 Prim算法是解决最小生成树的常用算法.它采取贪心策略,从指定的顶点开始寻找最小权值的邻接点.图G=<V,E>,初始时S={V0},把与V0相邻接,且边的权值最小的顶点加入到S.不断地把S中的顶点与V-S中顶点的最小权值边加入,直到所有顶点都已加入到S中

最小生成树のprim算法

Problem A Time Limit : 1000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submission(s) : 31   Accepted Submission(s) : 10 Problem Description 省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可).经过调查评估,得到的统计表中列出了有可能建设公

无向图最小生成树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算法的计算过程,参与维基百科的词条:[普里姆算法] 将上述点与点关系

E - Agri-Net (最小生成树) -- prim算法

http://acm.sdut.edu.cn:8080/vjudge/contest/view.action?cid=193#problem/E prim算法 思想和步骤总结 (自己所写) dis[],map[][],vis[],pos ,min,ans(主要定义的变量) 首先,prim算法用于计算图边径长度已知的图,它所求的是将图中所有顶点相连接,所需要的最短路径的长度,prim算法适合计算稠密图,它的主要思想是贪心思想,贪心准则为每次选择未加入树中且距离树最小的顶点,并用dis[]数组不断更

Highways POJ-1751 最小生成树 Prim算法

Highways POJ-1751 最小生成树 Prim算法 题意 有一个N个城市M条路的无向图,给你N个城市的坐标,然后现在该无向图已经有M条边了,问你还需要添加总长为多少的边能使得该无向图连通.输出需要添加边的两端点编号即可. 解题思路 这个可以使用最短路里面的Prim算法来实现,对于已经连接的城市,处理方式是令这两个城市之间的距离等于0即可. prim算法可以实现我们具体的路径输出,Kruskal算法暂时还不大会. 代码实现 #include<cstdio> #include<cs

最小生成树 Prim算法 Kruskal算法

最小生成树 给定一个无向图,如果它的某个子图中任意两个顶点都互相连通并且是一棵树,那么这棵树就叫做生成树,如果边上有权值,那么使得边权和最小的生成树叫做最小生成树. 常见的求解最小生成树的算法有Kruskal算法和Prim算法,生成树是否存在和图是否连通是等价的,所以假定图是连通的. Prim算法 假设有一棵只包含一个顶点v的数T,然后贪心地选取T和其他顶点之间相连的最小权值的边,并把它加到T中.不断进行这个操作,就可以得到最小生成树了(可用反证法证明) 不使用Heap优化的代码 int eg[