Description
给出N条公路和M个村庄以及每条公路的造价,求联通各个村庄的的最小的造价。
Input
测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M ( < 100 );随后的 N
行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从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
?
Solution
模板题
1. Prim算法,构造距离矩阵。
2. Kruscal,构造边。
code1
//Prim模板
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
const int maxn = 110, INF = 0x3f3f3f3f;
int N, M;
int cost[maxn][maxn], minicost[maxn];
bool used[maxn];
void init(int n, int m)
{
for (int i = 1; i <= m; i++)
{
used[i] = false;
for (int j = 1; j <= m; j++)
{
if (i == j)
cost[i][j] = 0;
else
cost[i][j] = INF;
}
}
}
int prim()
{
for (int i = 1; i <= M; i++)
minicost[i] = cost[1][i];
used[1] = true;
int ans = 0;
for (int i = 2; i <= M; i++)
{
int index = -1;
int minic = INF;
for (int j = 1; j <= M; j++)
if (!used[j] && minicost[j] < minic)
index = j, minic = minicost[j];
if (index == -1)
return 0;
used[index] = true;
ans += minic;
for (int k = 1; k <= M; k++)
if (!used[k])
minicost[k] = min(minicost[k], cost[index][k]);
}
return ans;
}
int main()
{
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
while (~scanf("%d%d", &N, &M) && N)
{
init(N, M);
for (int i = 1; i <= N; i++)
{
int t1, t2, t3;
scanf("%d%d%d", &t1, &t2, &t3);
cost[t1][t2] = cost[t2][t1] = t3;
}
int ans = prim();
if (ans == 0)
printf("?\n");
else
printf("%d\n", ans);
}
return 0;
}
code2
//Kruscal
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
struct edge
{
int u, v, w;
};
int pre[110], M, N;
edge edges[50010];
void init(int N, int M)
{
for (int i = 1; i <= M; i++)
pre[i] = i;
}
int find(int x)
{
if (x == pre[x])
return x;
return pre[x] = find(pre[x]);
}
void unite(int i, int j)
{
if (find(i) != find(j))
pre[j] = i;
}
bool cmp(edge a, edge b)
{
return a.w < b.w;
}
int main()
{
// freopen("in.txt", "r", stdin);
while (~scanf("%d%d", &N, &M) && N)
{
init(N, M);
for (int i = 1; i <= N; i++)
scanf("%d%d%d", &edges[i].u, &edges[i].v, &edges[i].w);
sort(edges + 1, edges + 1 + N, cmp);
int ans = 0;
for (int i = 1; i <= N; i++)
{
if (find(edges[i].u) != find(edges[i].v))
{
unite(edges[i].u, edges[i].v);
ans += edges[i].w;
}
}
int flag = false;
for (int i = 2; i <= M; i++)
{
if (find(1) != find(i))
{
flag = true;
break;
}
}
if (flag)
printf("?\n");
else
printf("%d\n", ans);
}
return 0;
}

本文详细介绍了使用Prim算法和Kruskal算法解决最小生成树问题的方法,并提供了完整的代码实现。通过对两种算法的具体步骤进行解析,帮助读者理解如何找到连接所有节点的最小代价路径。
1571

被折叠的 条评论
为什么被折叠?



