最小生成树---->prim算法的应用 hdu1863
来源:互联网 发布:程序员去汽车厂 编辑:程序博客网 时间:2024/06/01 19:56
畅通工程
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 27521 Accepted Submission(s): 12062
Problem Description
省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。现请你编写程序,计算出全省畅通需要的最低成本。
Input
测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M ( < 100 );随后的 N
行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。
行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。
Output
对每个测试用例,在1行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出“?”。
Sample Input
3 31 2 11 3 22 3 41 32 3 20 100
Sample Output
3?
//1. 假设有一棵树只包含一个顶点的v的树T。//2.贪心的选取T和其他顶点之间相连的最小权值的边,并将它加入T中.//3.不断重复1,2 直到所有的点相连生成一棵最小生成树。#include<queue>#include<stack>#include<math.h>#include<stdio.h>#include<numeric>//STL数值算法头文件#include<stdlib.h>#include<string.h>#include<iostream>#include<algorithm>#include<functional>//模板类头文件using namespace std;const int INF = 1e9+7;const int VM = 103;int G[VM][VM];//存图void prim(int n){ int record[VM];//记录 边的权值 bool vis[VM];//记录是否访问 int ans = 0; memset(vis, 0, sizeof(vis));//初始化 for (int i = 1; i <= n; i++) record[i] = G[1][i];//初始化 record[1] = 0; vis[1] = true;// 1 点标记为已访问 int i; for (i = 2; i <= n; i++) //进行 n - 1 次操作 { int u = INF;//初始化 int k; for (int j = 1; j <= n; j++) //遍历所有顶点 { if (!vis[j] && u > record[j]) //在所有的未加入的点中 找一个最小的权值 { k = j;//记录下标 u = record[j];//更新最小值 } } if (u == INF)//若图是不连通的 break;//提前退出 vis[k] = true;//标记为已加入 ans += u;//加权值 for (int j = 1; j <= n; j++) //遍历所有的点 { if (!vis[j] && record[j] > G[k][j])//对未加入的点&&能找到与此点相连且的权值最小的边 record[j] = G[k][j];//进行更新 } } //输出 if (i - 1 == n) printf("%d\n", ans); else printf("?\n");}int main(){ int n, m; while (scanf("%d %d", &n, &m), n) //对边数 和点数的获取 { for (int i = 1; i <= m; i++) //初始化 { for (int j = 1; j <= m; j++) { G[i][j] = i == j ? 0 : INF; } } while (n--) { int u, v, w; scanf("%d %d %d", &u, &v, &w);//获取 数据 if (G[u][v] > w)//防止重边&&存两点之间的最短距离 G[u][v] = G[v][u] = w; } prim(m);//调用函数 } return 0;}
优化#include <queue>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define LL long longusing namespace std;const int INF = 1e9+7;const int VM = 103;typedef pair<int, int>P;//对组struct node //前向星 结构体{ int v, w; int next;};node edge[4 * VM];//前向星数组int head[VM];//头指针数组int cnt;//计数void add(int u, int v, int w) //加边函数{ edge[cnt].v = v;//顶点 edge[cnt].w = w;//权值 edge[cnt].next = head[u];//下一个 head[u] = cnt++;//头指针}void prim(int n) //普利姆函数{ bool vis[VM];//标记是否访问过 int record[VM];//记录权值 int ans = 0;//最小生成树的总值 int count = 0;//计数 priority_queue<P, vector<P>, greater<P> >que;//权值从小到大的队列 fill(record, record + VM, INF);//初始化 memset(vis, 0, sizeof(vis));//初始化 record[1] = 0;//初始化 que.push(P(0, 1));//将 1点 和 record[1] = 0 放入队列 while (!que.empty()) //队列不为空时 { P p = que.top();//取出队首 que.pop();//删除 int u = p.second;// if (vis[u] == true)//若此顶点已经加入生成树 continue;// vis[u] = true;//否则,就标记为加入 ans += record[u];// count++;//加入点个数 for (int i = head[u]; i != -1; i = edge[i].next) //遍历与该点相邻的点 { node e = edge[i]; if (record[e.v] > e.w) //更新他们的权值 { record[e.v] = e.w;// que.push(P(record[e.v], e.v));//放入队列 } } } //输出 if (count == n) printf("%d\n", ans); else printf("?\n");}int main(){ int n, m; while (scanf("%d %d", &n, &m), n) //边的个数 顶点个数 { memset(head, -1, sizeof(head));//初始化 cnt = 0;//初始化 while (n--) { int u, v, w; scanf("%d %d %d", &u, &v, &w);//获取数据 add(u, v, w);//加边 add(v, u, w);//无向图 } prim(m);//普利姆算法 } return 0;}//克鲁斯卡尔算法用并查集的优化#include <queue>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define LL long longusing namespace std;const int INF = 1e9+7;const int VM = 103;struct node //边的结构体{ int u, v, w;};node edge[VM * 2];int high[VM];//分组的高度int par[VM];//父节点bool cmp(const node &a, const node &b){ return a.w < b.w;//按w从小到大排序}int find(int x){ if(x!=par[x]) x=find(par[x]); return par[x];}bool same(int x, int y) //判断为否在同一分组中{ return find(x) == find(y);}int unite(int x, int y){ x = find(x);//查找根节点 y = find(y);//查找根节点 if(x!=y) { par[x]=y; high[x]++; }}int main(){ int n, m; while (scanf("%d %d", &n, &m), n) //获取边的个数 和顶点个数 { int cnt = 0;// for (int i = 1; i <= m; i++)//初始化 par[i] = i; memset(high, 0, sizeof(high));//初始化 while (n--) { scanf("%d %d %d", &edge[cnt].u, &edge[cnt].v, &edge[cnt].w);//获取数据 cnt++; } sort(edge, edge + cnt, cmp);//按权值从小到大排序 int ans = 0;//最小生成树 权值 int count = 0;//计数 for (int i = 0; i < cnt; i++) //对所有的边 { node e = edge[i]; if (!same(e.u, e.v)) //若两点不属于一个分组 { ans += e.w;//权值总和 unite(e.u, e.v);//合并两点 count++;//计数 } } //输出 if (count == m - 1) printf("%d\n", ans); else printf("?\n"); } return 0;}
0 0
- 最小生成树---->prim算法的应用 hdu1863
- HDU1863---最小生成树(prim算法)
- hdu1863(最小生成树--Prim算法)
- HDU1863 - 畅通工程 Prim最小生成树算法
- HDU1863 畅通工程 【最小生成树Prim】
- HDU1863 最小生成树 prim模版
- HDU1863:畅通工程2(最小生成树Kruskal算法与Prim算法)
- hdu1863 畅通工程(最小生成树之prim)
- Kruskal & Prim 最小生成树HDU1863 畅通工程
- 最小生成树 Prim算法的实现及应用
- Prim算法的实现及应用( 最小生成树)
- Prim 算法生成的最小生成树
- HDU1863(最小生成树)
- HDU1863最小生成树
- 最小生成树的prim算法代码
- 最小生成树的prim算法实现
- 构造最小生成树的 prim 算法
- 最小生成树的Prim算法
- POJ 3366 Deli Deli 可能会
- MDK环境下stm32实现printf函数
- 面试题16:反转链表
- [POJ]2739-Sum of Consecutive Prime Numbers
- ural1014 Product of Digits (枚举)
- 最小生成树---->prim算法的应用 hdu1863
- PAT A1056. Mice and Rice (25)
- ubuntu16.04忘记密码处理方法
- Codeforces Round #399 (Div. 1 + Div. 2, combined)C. Jon Snow and his Favourite Number
- 各项知识链接集合(比较杂)
- [HTC Vive + Unity开发]——VRTK的研究——用手柄旋转物体(使用VRTK_Knob脚本)
- TCP/IP 多播和多播路由
- bootstrap折叠调用collapse()后data-parent不生效问题
- csdn上第一篇博客