【最小生成树入门专题1】G

来源:互联网 发布:知乎老人吸烟猝死案 编辑:程序博客网 时间:2024/06/05 10:13

省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。现请你编写程序,计算出全省畅通需要的最低成本。 
Input
测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M ( < 100 );随后的 N 
行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。 
Output
对每个测试用例,在1行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出“?”。 
Sample Input
3 31 2 11 3 22 3 41 32 3 20 100
Sample Output
3?

此处应有板砖,一道纯模板题,自己活生生的wrong了3遍才过,第一点,应找到最少为顶点n-1条边才推出循环,而不是循环到m条边,第二点,好歹用个变量存下已经找到的边的数目啊,第三!!!输出最小路径的权值哎哟喂,怎么输出找到的边的个数啊,下次引以为戒,简直太过分了

#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;#define N 1000struct edge{int u,v,w;};edge e[N];int f[N];int find (int e){if(f[e] == e)return e;else{f[e] = find(f[e]);return f[e];}}int merge(int a,int b){int t1,t2;t1 = find(a);t2 = find(b);if(t1!=t2){f[t1] = t2;return 1;}return 0;}int cmp(edge a,edge b){return a.w < b.w ;}int main(){int n,m,sum,i,count;while(scanf("%d",&m),m!=0){sum = 0;count = 0;scanf("%d",&n);for(i = 1; i <= n; i ++)f[i] = i;for(i = 1; i <= m; i ++)scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);sort(e+1,e+1+m,cmp);for(i = 1; i <= m; i ++){if(merge(e[i].u,e[i].v)){sum += e[i].w ;count ++;}if(count == n-1)break;}if(count < n-1)printf("?\n");elseprintf("%d\n",sum);}return 0;}

B - 这是水题2

 


描述

随着小Hi拥有城市数目的增加,在之间所使用的Prim算法已经无法继续使用了——但是幸运的是,经过计算机的分析,小Hi已经筛选出了一些比较适合建造道路的路线,这个数量并没有特别的大。

所以问题变成了——小Hi现在手上拥有N座城市,且已知其中一些城市间建造道路的费用,小Hi希望知道,最少花费多少就可以使得任意两座城市都可以通过所建造的道路互相到达(假设有A、B、C三座城市,只需要在AB之间和BC之间建造道路,那么AC之间也是可以通过这两条道路连通的)。

提示:积累的好处在于可以可以随时从自己的知识库中提取想要的!

输入

每个测试点(输入文件)有且仅有一组测试数据。

在一组测试数据中:

第1行为2个整数N、M,表示小Hi拥有的城市数量和小Hi筛选出路线的条数。

接下来的M行,每行描述一条路线,其中第i行为3个整数N1_i, N2_i, V_i,分别表示这条路线的两个端点和在这条路线上建造道路的费用。

对于100%的数据,满足N<=10^5, M<=10^6,于任意i满足1<=N1_i, N2_i<=N, N1_i≠N2_i, 1<=V_i<=10^3.

对于100%的数据,满足一定存在一种方案,使得任意两座城市都可以互相到达。

输出

对于每组测试数据,输出1个整数Ans,表示为了使任意两座城市都可以通过所建造的道路互相到达至少需要的建造费用。

Sample Input
5 291 2 6742 3 2493 4 6724 5 9331 2 7883 4 1472 4 5043 4 381 3 653 5 61 5 8651 3 5901 4 6822 4 2272 4 6361 4 3121 3 1432 5 1582 3 5163 5 1021 5 6051 4 994 5 2242 4 1983 5 8941 5 8453 4 72 4 141 4 185
Sample Output
92


 看着这个我还以为是啥新的算法呢,结果又是kruskal 模板题  自行注意数据范围(因此wrong2遍的飘过  把10的6次方看做10万的数据也会醉了)

#include<stdio.h>#include<algorithm>using namespace std;#define N 1110000struct edge{int u,v,w;};edge e[N];int f[N];int find (int e){if(f[e] == e)return e;else{f[e] = find (f[e]);return f[e];}}int merge(int u,int v){int t1,t2;t1 = find (u);t2 = find (v);if(t1!=t2){f[t1] = t2;return 1;}return 0;}int cmp(edge a,edge b){return a.w < b.w ;}int main(){int n,m,sum,count,i;while(scanf("%d%d",&n,&m)!=EOF){sum = 0;count = 0;for(i = 1; i <= n; i ++)f[i] = i;for(i = 1; i <= m; i ++)scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);sort(e+1,e+1+m,cmp);for(i = 1; i <= m; i ++){if(merge(e[i].u,e[i].v)){sum += e[i].w ;count ++;}if(count == n-1)break;}printf("%d\n",sum);}return 0;}




原创粉丝点击