畅通工程
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 28901 Accepted Submission(s): 12688
Problem Description
省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。现请你编写程序,计算出全省畅通需要的最低成本。
Input
测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M ( < 100 );随后的 N
行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。
行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。
Output
对每个测试用例,在1行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出“?”。
Sample Input
3 3 1 2 1 1 3 2 2 3 4 1 3 2 3 2 0 100
Sample Output
3 ?
思路:使用Prime算法或者Kruskal算法求最小生成树
我使用Prime算法,由于Prime算法的实现方式不同,可能输出?的判断条件不同,我采用的是《挑战程序设计竞赛》(第2版)的Prime算法,而其他的比如 http://blog.csdn.net/chenguolinblog/article/details/7994169 的作者的输出?的判断条件则不同
欢迎交流:
#include <cstdio>
#include <string.h>
#include<algorithm>
using namespace std;
int const INF = 0x3f3f3f3f;
int const MAX_V = 110;
int cost[MAX_V][MAX_V];//cost[u][v]表示边e=(u,v)的权值
int mincost[MAX_V];//从集合X(已经求得的生成树的顶点集合)出发的边到每个顶点的最小权值(不存在的情况下设为INF)
bool used[MAX_V];//顶点i是否包含在集合X中
int V;//顶点数
void prim()
{
for (int i = 1; i <= V; i++)
{
mincost[i] = INF;
used[i] = false;
}
mincost[1] = 0;
int res = 0;
while (true)
{
int v = -1;
//从不属于X的顶点中选取从X到其权值最小的顶点
for (int u = 1; u <= V; u++)
{
if (!used[u] && (v == -1 || mincost[u] < mincost[v]))v = u;
}
if (v == -1)break;
used[v] = true;//把顶点v加入到X
res += mincost[v];//把边的长度加到结果中
for (int u = 1; u <= V; u++)
{
mincost[u] = min(mincost[u], cost[v][u]);
}
}
if (res>=INF) printf("?\n");//把不存在的边加入到结果中,res比如>=INF
else printf("%d\n", res);
}
int main()
{
int n;
int i=0, j=0;
while (scanf("%d", &n) != EOF&&n)
{
memset(cost, INF, sizeof(cost));
scanf("%d",&V);
while (n--)
{
scanf("%d%d", &i,&j);
scanf("%d", &cost[i][j]);
cost[j][i] = cost[i][j];//无向图
}
prim();
}
return 0;
}