一看就是最小生成树
图论很久没看了,想抽时间系统地看下
所以直接把以前的模板贴上了
题目有陷阱就是读入字符如果用scanf来做会很恶心
因为每一行末尾可能有多个空格,只用getchar()会RE
所以直接用cin处理即可
代码如下:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAXN 1010
#define INF 0x7fffffff
#define ll long long
using namespace std;
int map[MAXN][MAXN];
int dis[MAXN];
int n;
int prim(void){
int now;
int minedge,minnode;
for(int i=0;i<n;i++)
dis[i] = INF;
now = 0;
int ans = 0;
for(int i=0; i<n-1; i++){
dis[now] = -1;
minedge = INF;
for(int j=0; j<n; j++) {
if(j!=now && dis[j]>=0) {
if(map[now][j] > 0) {
dis[j] = min(dis[j], map[now][j]);
}
if(dis[j] < minedge) {
minedge = dis[j];
minnode = j;
}
}
}
now = minnode;
ans += minedge;
}
return ans;
}
int main(void) {
int t, x, y, dis;
char ch;
while(cin >> n, n) {
memset(map, 0, sizeof(map));
for(int c=0; c<n-1; ++c) {
cin >> ch;
x = ch-'A';
cin >> t;
for(int i=0; i<t; ++i) {
cin >> ch >> dis;
y = ch-'A';
map[x][y] = dis;
map[y][x] = dis;
}
}
/*
for(int i=0; i<n; ++i) {
for(int j=0; j<n; ++j) {
if(map[i][j]) {
printf("map[%c][%c] = %d\t", i+'A', j+'A', map[i][j]);
}
}
printf("\n");
}
*/
printf("%d\n", prim());
}
return 0;
}
刚刚在练习克鲁斯卡尔算法,对着模板写了下,把代码也贴在这吧
#include <cstdio>
#include <iostream>
#include <algorithm>
#define MAXN 1010
#define ll long long
using namespace std;
int u[MAXN], v[MAXN], w[MAXN];
int p[MAXN], r[MAXN];
int n, m, cnt;
int cmp(const int i, const int j) {
return w[i]<w[j];
}
int find(int x) {
return p[x]==x ? x : p[x]=find(p[x]);
}
int Kruskal() {
int ans = 0;
for(int i=0; i<n; ++i)
p[i] = i;
for(int i=0; i<cnt; ++i)
r[i] = i;
sort(r, r+cnt, cmp);
for(int i=0; i<cnt; ++i) {
int e = r[i];
int x = find(u[e]);
int y = find(v[e]);
if(x != y) {
ans += w[e];
p[x] = y;
}
}
return ans;
}
int main(void) {
char ch1, ch2;
while(scanf("%d", &n), n) {
cnt = 0;
for(int i=0; i<n-1; ++i) {
getchar();
ch1 = getchar();
scanf("%d", &m);
while(m--) {
getchar();
ch2 = getchar();
u[cnt] = ch1-'A';
v[cnt] = ch2-'A';
scanf("%d", &w[cnt]);
cnt++;
}
}
cout << Kruskal() << endl;
}
return 0;
}