poj 丛林中的树
来源:互联网 发布:不在乎大国崛起 知乎 编辑:程序博客网 时间:2024/04/28 16:42
热带岛屿Lagrishan的首领现在面临一个问题:几年前,一批外援资金被用于维护村落之间的道路,但日益繁茂的丛林无情的侵蚀着村民的道路,导致道路维修开销巨大,长老会不得不放弃部分道路的维护。上图左侧图显示的是正在使用道路的简图以及每条路每个月的维修费用(单位为aacms)。现在长老会需要提出一种方案,即需要保证村落之间都可以互相到达,又要将每个月的道路维修费用控制在最小。村子编号为从A到I。上图右侧显示的方案最小维修开销为216 aacms每月。
提示:蛮力算法虽能找出解决方案,但将会超出时间限制。
9A 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 200
21630
思路:最小生成树即可,用克鲁斯卡尔算法或者prim算法
注意输入和输出的区别,还有注意每次计算完毕,再下一组数据前要清空数据。不然一些测试数据会WA。
#include <stdio.h>#include <algorithm>using namespace std;int tree[101];int findroot(int x){if(tree[x]==-1)return x;else{int tmp=findroot(tree[x]);tree[x]=tmp; //路径压缩return tmp;}}struct Edge{int a,b;int cost;bool operator < (const Edge &A) const{return cost<A.cost;}}edge[101];int main(){//freopen("1251.txt","r",stdin);int n;while(scanf("%d", &n)!=EOF && n!=0){char head;char tail;int cost;int m;int size=0;int n_=n-1;while(n_--){ scanf(" %c %d",&head,&m); //注意字符输入问题,回车键也会被当成一个字符,所以%c前要加一个空格 while(m--){ scanf(" %c %d",&tail,&cost); edge[size].a=(int)(head-'A'); edge[size].b=(int)(tail-'A'); edge[size].cost=cost; size++;}}sort(edge,edge+size);for(int i=0;i<n;i++){ //若这里的n换成了size的话,也会报错,因为村落的数目为n,而size的数目在测试集上有可能为n-1(已经是最小生成树的那种的)。 tree[i]=-1;}int ans=0;for(int i=0;i<size;i++){int a=findroot(edge[i].a);//找到a的集合 。 int b=findroot(edge[i].b);//找到b的集合。 if(a!=b){tree[a]=b;ans+=edge[i].cost;}}printf("%d\n", ans);}return 0;}
下面是用prim算法实现的最小生成树,
prim算法实现的几个关键点
1,用3个不同的数据结构 vis数组(标识每个节点是否访问过),dis数组(记录每个边的大小,注意与迪杰特斯拉算法的区别),w的权重矩阵
存放时点和点之间的权重。
2,prim函数里面,遍历时只需要遍历n-1次,因为n个节点的生成树只有n-1条边。
3,初始化问题,尽量用memset函数。
AC代码
#include<iostream>#include<cstring>using namespace std;const int inf=10000; int graph[101][101];int dis[101];bool vis[101];char c1,c2;int cost;int num;int t;void prim(){int ans = 0;int k;graph[0][0] = 0;for(int i =0; i < t; i++ )dis[i] = graph[0][i];vis[0] = true;for(int i =0; i< t -1;i++){ //t-1 edgesfor(int j = 0,min = inf; j < t ;j++){if(min > dis[j] && !vis[j]){min = dis[j];k = j;}}ans += dis[k];//cout<<dis[k]<<endl;vis[k] = true;for(int j=0;j < t;j++){if(graph[k][j] < dis[j] && !vis[j]){dis[j] = graph[k][j]; //update the distance }}}cout << ans <<endl;}int main(){while(cin >> t && t!= 0){memset(graph,inf,sizeof(graph));memset(vis,false,sizeof(vis));for(int j =0 ; j < t-1;j++){cin >> c1 >> num;for(int i=0; i < num ;i++){cin >>c2>>cost;int s = (int)(c1 - 'A'); int e = (int)(c2 - 'A');graph[s][e] = cost;graph[e][s] = cost;}}for(int i =0;i<t;i++)graph[i][i] = 0;prim();} return 0;}
这个prim算法卡了1个小时,自己水平太次了。。。大二就学过,但没有自己亲自动手实现过,等于没学。
阅读全文
0 0
- poj 丛林中的树
- 百练1251:丛林中的树
- POJ 1251 丛林道路
- poj 1251 丛林中的路 最小生成树问题 克鲁斯卡方法 并查集解决
- 人性丛林中的忌讳
- openjudge 丛林中的路
- 丛林中的路
- 丛林中的路
- 2nd 【最小生成树】 丛林中的树
- hdu 1301 Jungle Roads(丛林中的道路) 最小生成树
- OpenJudge noi253 丛林中的路
- 兔子与星空&&丛林中的路
- 丛林法则
- 丛林探险
- 丛林探险
- 九度OJ 1154:Jungle Roads(丛林路径) (最小生成树)
- 我步入丛林
- 丛林生存法则
- 整理中:使用 Visual Studio Code (vscode) 编写、运行、 调试 Java 应用程序
- 第三周项目3-求集合并集
- RS232串口通信详解
- centos6.9编译安装httpd2.4(1)
- 实验五:用callback增强链表模块来实现命令行菜单小程序V2.8
- poj 丛林中的树
- web.xml
- 一次简单的线上OOM调试
- C++面向对象程序设计持续总结中。。。
- C++STL 常用 函数 用法
- centos7重新调整分区大小
- C++文件操作
- 总结7
- surfire 单元测试 使用了mock字节码再生和注入, UseSplitVerifier防止字节码校验