题目概述
有P个地点,R条双向路,求其最小生成树边权和
时限
1000ms/3000ms
输入
第一行整数P,R,其后R行,每行三个整数a,b,c,描述a到b之间的一条路径,权值为c,输入到P=0结束
限制
1<=P<=50;1<=R<=100
输出
每行一个数,为所求边权和
样例输入
1 0
2 3
1 2 37
2 1 17
1 2 683 7
1 2 19
2 3 11
3 1 7
1 3 5
2 3 89
3 1 91
1 2 325 7
1 2 5
2 3 7
2 4 8
4 5 11
3 5 10
1 5 6
4 2 120
样例输出
0
17
16
26
讨论
图论,最小生成树,prim算法,没什么说的,很直白,求就是
由于题目相当直白,因此再转述也没什么意思,直接就把模型抽象好了
题解状态
176K,16MS,C++,1028B
题解代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define MAXN 52
#define memset0(a) memset(a,0,sizeof(a))
int P, R;//地点总数 路径总数
int graph[MAXN][MAXN], dis[MAXN];//邻接矩阵 两点间最短距离
bool mk[MAXN];//已在树中的标记
int fun()
{
for (int p = 1; p <= P; p++)
for (int i = p + 1; i <= P; i++)
graph[p][i] = graph[i][p] = INF;//初始化邻接矩阵
for (int p = 0; p < R; p++) {
int a, b, c;
scanf("%d%d%d", &a, &b, &c);//input
graph[a][b] = graph[b][a] = min(graph[a][b], c);
}
int sum = 0;//边权和
for (int p = 1; p <= P; p++) {
dis[p] = graph[1][p];//初始化最短距离数组
mk[p] = 0;
}
mk[1] = 1;//第一个点加入树 下面是prim主体
for (int p = 1; p < P; p++) {
int least = INF, pos;
for (int p = 1; p <= P; p++)
if (!mk[p] && least>dis[p]) {
least = dis[p];
pos = p;
}
mk[pos] = 1;
sum += least;
for (int p = 1; p <= P; p++)
if (!mk[p] && dis[p] > graph[pos][p])
dis[p] = graph[pos][p];
}
return sum;
}
int main(void)
{
//freopen("vs_cin.txt", "r", stdin);
//freopen("vs_cout.txt", "w", stdout);
while (~scanf("%d%d", &P, &R) && P) {//input
printf("%d\n", fun());//output
}
}
EOF