明天就考高数了,我竟然在学算法……
新学会个最小生成树,找了个模版题试试,AC了就很开心!
这道题其实就是套模版,但是这个算法很有趣。
代码:
// 最小生成树
include <cstdio>
#include <climits>
#include <cstring>
const int maxn = 30;
int n;
int road[maxn][maxn];
int dis[maxn];
int vis[maxn];
void input() { // 注意本题输入形式
char u[2];
char node[2];
int d, N;
for(int i = 0; i < n -1 ; i++) {
scanf("%s%d", u, &N);
while(N--) {
scanf("%s%d", node, &d);
road[u[0]-'A'][node[0]-'A'] = road[node[0]-'A'][u[0]-'A'] = d;
}
}
}
void prim() { // 用这个函数计算和打印结果,顾名思义用了prim算法……
int min_dis;
int v;
int sum = 0;
for(int i = 1; i < n; i++) { // 一开始确定一个节点,确定该节点与其他节点的distance,如果是-1则代表不相连
dis[i] = road[0][i];
}
vis[0] = 1;
dis[0] = 0;
int cnt = n;
while(cnt--) {
min_dis = INT_MAX;
for(int j = 0; j < n; j++) { // 找到到已遍历节点路程最短的节点
if (!vis[j] && dis[j] != -1 && min_dis > dis[j]) {
v = j;
min_dis = dis[j];
}
}
vis[v] = 1; // 标记遍历过该节点
for(int i = 0; i < n; i++) { // 找到新加入节点与未遍历节点的关系,更新dis状态……
if (!vis[i] && road[v][i] != -1 && (road[v][i] < dis[i] || dis[i] == -1)) { // 这个`或`值得想一下,一种可能是之前遍历过的节点未与该节点相连,一种是路程小于以前的节点,一开始没考虑好老是过不了用例
dis[i] = road[v][i];
}
}
}
for(int i = 0; i < n; i++) {
sum += dis[i];
}
printf("%d\n", sum);
}
void init() {
memset(road, -1, sizeof(road)); //把road里的值都弄成-1
memset(vis, 0, sizeof(vis));
for(int i = 0; i < n; i++) {
road[i][i] = 0; //节点和自己连路程当然是0喽
}
};
int main() {
//freopen("input.txt", "r", stdin);
while(~scanf("%d", &n) && n) {
init();
input();
prim();
}
return 0;
}