hdu 1879 继续畅通工程
来源:互联网 发布:电脑安装软件失败 编辑:程序博客网 时间:2024/06/06 06:52
继续畅通工程
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 13934 Accepted Submission(s): 6064
Problem Description
省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。现得到城镇道路统计表,表中列出了任意两城镇间修建道路的费用,以及该道路是否已经修通的状态。现请你编写程序,计算出全省畅通需要的最低成本。
Input
测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( 1< N < 100 );随后的 N(N-1)/2 行对应村庄间道路的成本及修建状态,每行给4个正整数,分别是两个村庄的编号(从1编号到N),此两村庄间道路的成本,以及修建状态:1表示已建,0表示未建。
当N为0时输入结束。
当N为0时输入结束。
Output
每个测试用例的输出占一行,输出全省畅通需要的最低成本。
Sample Input
31 2 1 01 3 2 02 3 4 031 2 1 01 3 2 02 3 4 131 2 1 01 3 2 12 3 4 10题目大意:计算实现城通工程的,修路的最低成本难点:有的路已经修好,不能计算在内,且不能有回路关键点:开始赋值的预处理,把已经修好的路的根节点合并在一起解题时间:2014,08,19解题思路:最小生成树的Kruskal算法,注意已经修好的路体会:一开始也不知道怎么处理已经修好的路,参考别人的代码才明白最小生成树还得练****************************/#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;struct xinxi{int m;int n;int cb;int zt;}a[5100];bool cmp(struct xinxi a,struct xinxi b){//对成本进行生序排列 return a.cb<b.cb;}int x[110];int find(int a){//寻找根节点 if(x[a]!=a)x[a]=find(x[a]); return x[a];}int main(){int n,i,k,g,t,sum,num;while(scanf("%d",&n),n){for(i=0;i<110;i++)x[i]=i;t=n*(n-1)/2;for(i=0;i<t;i++){scanf("%d%d%d%d",&a[i].m,&a[i].n,&a[i].cb,&a[i].zt);if(a[i].zt==1){//如果路已经修好,那么把这条路的两端的村子合并到一个集合 k=find(a[i].m);//试根节点一样,以避免下边计算重复 g=find(a[i].n);if(k!=g) x[g]=k;}}sort(a,a+t,cmp);//sort排序 sum=num=0;for(i=0;i<t&&num<n-1;i++){k=find(a[i].m);g=find(a[i].n);if(k!=g){x[g]=k;sum+=a[i].cb;num++;}}printf("%d\n",sum);}return 0;}////克鲁斯卡尔算法(Kruskal's algorithm)是两个经典的最小生成树算法的较为简单理解的一个。这里面充分体现了贪心算法的精髓。大致的流程可以用一个图来表示。这里的图的选择借用了Wikipedia上的那个。非常清晰且直观。首先第一步,我们有一张图,有若干点和边如下图所示:.第一步我们要做的事情就是将所有的边的长度排序,用排序的结果作为我们选择边的依据。这里再次体现了贪心算法的思想。资源排序,对局部最优的资源进行选择。排序完成后,我们率先选择了边AD。这样我们的图就变成了......第二步,在剩下的边中寻找。我们找到了CE。这里边的权重也是5......依次类推我们找到了6,7,7。完成之后,图变成了这个样子。......下一步就是关键了。下面选择那条边呢? BC或者EF吗?都不是,尽管现在长度为8的边是最小的未选择的边。但是他们已经连通了(对于BC可以通过CE,EB来连接,类似的EF可以通过EB,BA,AD,DF来接连)。所以我们不需要选择他们。类似的BD也已经连通了(这里上图的连通线用红色表示了)。最后就剩下EG和FG了。当然我们选择了EG。最后成功的图就是下图:......到这里所有的边点都已经连通了,一个最小生成树构建完成。Kruskal算法的时间复杂度由排序算法决定,若采用快排则时间复杂度为O(N log N)。3代码实现编辑
伪代码
MST-KRUSKAL(G,w)C
12345678910111213141516171819202122232425262728293031323334353637383940414243#include"stdio.h"
#include"stdlib.h"
struct edge
{
int m;
int n;
int d;
}a[5010];
int cmp(const void *a,const void *b)
//按升序排列
{
return
((struct edge *)a)->d>((struct edge *)b)->d;
}
int main(
void
)
{
int i,n,t,num,min,k,g,x[100];
printf
(
"请输入顶点的个数:"
);
scanf
(
"%d"
,&n);
t=n*(n-1)/2;
for
(i=1;i<=n;i++)
x[i]=i;
printf
(
"请输入每条边的起始端点、权值:/n"
);
for
(i=0;i<t;i++)
scanf
(
"%d%d%d"
,&a[i].m,&a[i].n,&a[i].d);
//输入每条边的权值
qsort
(a,t,
sizeof
(a[0]),cmp);
min=num=0;
for
(i=0;i<t&&num<n-1;i++)
{
for
(k=a[i].m;x[k]!=k;k=x[k])
//判断线段的起始点所在的集合
x[k]=x[x[k]];
for
(g=a[i].n;x[g]!=g;g=x[g])
//判断线段的终点所在的集合
x[g]=x[x[g]];
if
(k!=g)
//如果线段的两个端点所在的集合不一样
{
x[g]=k;
min+=a[i].d;
num++;
printf
(
"最小生成树中加入边:%d%d/n"
,a[i].m,a[i].n);
}
}
printf
(
"最小生成树的权值为:%d/n"
,min);
system
(
"pause"
);
return 0;
}
0 0
- HDU 1879 继续畅通工程
- 继续畅通工程 hdu 1879
- hdu 1879 继续畅通工程
- HDU 1879 继续畅通工程
- hdu 1879 继续畅通工程
- hdu 1879 继续畅通工程
- HDU 1879 继续畅通工程
- hdu 1879 继续畅通工程
- hdu 1879 继续畅通工程
- hdu 1879 继续畅通工程
- HDU 1879 继续畅通工程
- hdu 1879 继续畅通工程
- hdu - 1879 - 继续畅通工程
- hdu 1879 继续畅通工程
- hdu 1879 继续畅通工程
- hdu 1879 继续畅通工程
- hdu 1879(继续畅通工程)
- hdu 1879 继续畅通工程
- ns3 常用waf命令
- POJ 2524 Ubiquitous Religions //简单并查集
- Java基础- super 和 this 解析
- C# 从路径加载图片
- cocos2dx 内存管理
- hdu 1879 继续畅通工程
- iOS开发那些事-移动平台架构设计
- log4j迁移到logback
- Spring 注解@Transactional
- 随机梯度下降法求解SVM(附matlab代码)
- 【BZOJ】【P1324】【Exca王者之剑】【题解】【最小割】
- debian 编译内核
- VBS发送邮件
- 计算机中的树(来自百度百科)