HDUOJ_1863(畅通工程) (最小生成树)(prim和克鲁斯卡尔两种方法解)
2015-08-11 23:12
330 查看
HDUOJ_1863(畅通工程) (最小生成树)(prim和克鲁斯卡尔两种方法解)
畅通工程
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 21514 Accepted Submission(s): 9274
[align=left]Problem Description[/align]
省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。现请你编写程序,计算出全省畅通需要的最低成本。
[align=left]Input[/align]
测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M ( < 100 );随后的 N
行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。
[align=left]Output[/align]
对每个测试用例,在1行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出“?”。
[align=left]Sample Input[/align]
3 3
1 2 1
1 3 2
2 3 4
1 3
2 3 2
0 100
[align=left]Sample Output[/align]
3
?
My solution:
/*2015.8.11*/
/*用克鲁斯卡尔算法解*/
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; int per[10000]; struct stu { int u,v,w; }node[110]; int cmp(stu a,stu b) { return a.w<b.w; } void chushihua() { int i; for(i=1;i<10000;i++) per[i]=i; } int find(int x) { int i,j; i=x; while(x!=per[x]) x=per[x]; while(i!=per[i]) { j=per[i]; per[i]=x; i=j; } return x; } bool join(int x, int y)/*注意和并查集的代码区分,并查集中的连接函数没有返回值*/ { int fx,fy; fx=find(x); fy=find(y); if(fx!=fy) { per[fy]=fx; return true; } else return false; } int main() { int i,j,n,m,sum=0,count=0; while(scanf("%d%d",&m,&n)==2&&m) { chushihua();/*注意:这个函数经常容易忘记调用*/ count=0;sum=0; for(i=0;i<m;i++) scanf("%d%d%d",&node[i].u,&node[i].v,&node[i].w); sort(node,node+m,cmp);/*把成本从小到大排序,先修成本小的道路*/ for(i=0;i<m;i++) { /*判断两个村庄是否已经连通,若已连通,则不再连接*/ if(join(node[i].u,node[i].v))/*判断两个点的根节点是否相同,若相同则不连接,从而避免成环*/ sum+=node[i].w;/*统计成本*/ } for(i=1;i<=n;i++) { if(i==per[i]) count++;/*通过遍历,查找有几个根节点*/ } if(count==1)/*若只有一个根节点,说明村庄全部连通,否则说明没有全部连通*/ printf("%d\n",sum); else printf("?\n"); } return 0; }
/*2015.8.13*/
/*用prim解*/
#include<stdio.h> #include<string.h> #define INF 0X3F3F3F3F/*定义无穷大*/ int path[110]; int dis[110][110]; int n; int mark[110]; void prim() { int v,i,j,k,sum=0,min; memset(mark,0,sizeof(mark)); for(i=2;i<=n;i++) path[i]=dis[1][i]; mark[1]=1; for(i=1;i<n;i++) { min=INF; for(j=1;j<=n;j++) if(!mark[j]&&path[j]<min) { k=j; min=path[j]; } if(min==INF) { printf("?\n"); return ; } mark[k]=1; sum+=path[k]; for(j=1;j<=n;j++) if(!mark[j]&&path[j]>dis[k][j]) path[j]=dis[k][j]; } printf("%d\n",sum); } int main() { int m,i,a,b,c; while(scanf("%d%d",&m,&n)==2&&m) { /*把数组全部初始化为无穷大,这个方法一定要记住*/ memset(dis,0x3f,sizeof(dis));/*把所有的边权值全部赋值为无穷大,在下面输入数据时可以进行覆盖,这样可以解决有些边没权值时,不能参与点的筛选*/ for(i=1;i<=m;i++) { scanf("%d%d%d",&a,&b,&c); //if(dis[a][b]>c) /*输入的数据可能会有重边,如 1 2 3之后又输入一组数据输入2 1 4,导致重边,而且后输入的数据会覆盖*/ dis[a][b]=dis[b][a]=c; /*之前的数据为了保留最小的边权值,此时需在这里加上一个if判断,不过此题不加也AC了。但是这个问题要时刻注意*/ } prim(); } return 0; }
相关文章推荐
- 无约束最优化方法学习笔记
- POJ3349---Snowflake Snow Snowflakes
- zoj 2334 分类: zoj templa...
- hdu 1394(BIT求逆序数)
- 黑马程序员——高新技术---反射
- zoj 2334
- The shortest problem(hdu5373+11的倍数)
- zoj 2334 分类: zoj templates 2015-08-11 23:12 2人阅读 评论(0) 收藏
- C++与C#互调dll的实现步骤
- 归档告警频繁监控脚本
- ViewPager
- 我的前端学习笔记 box-sizing,calc,回调函数
- Java小游戏之打飞机(二)
- C++嵌入Python语言(一):环境搭建及HelloWord程序测试
- 第一百三十一天 how can I 坚持
- IOS 30多个iOS常用动画,带详细注释
- BZOJ 1877: [SDOI2009]晨跑( 最小费用最大流 )
- Maven Web项目构建
- FragmentTabHost
- 通过顶点颜色,制作高级贴图混合效果····