题意:
输入n,然后接下来有n-1行表示边的加边的权值情况。如A 2 B 12 I 25 表示A有两个邻点,B和I,A-B权值是12,A-I权值是25。求连接这棵树的最小权值。
思路:
一开始是在做莫队然后发现没学过最小生成树,就跑过来做模板题了...
Kruskal的使用过程:先按权值大小排序,然后用并查集判断是否能加这条边
Kruskal详解博客:【贪心法求解最小生成树之Kruskal算法详细分析】---Greedy Algorithm for MST
考试周还在敲代码...我...
代码:
#include<queue>
#include<cstring>
#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<vector>
#include<cstdio>
#include<iostream>
#include<algorithm>
#define ll long long
const int N = 1e5+5;
const int MOD = 10007;
using namespace std;
struct edge{
int u,v,value;
friend bool operator < (edge a,edge b){
return a.value < b.value;
}
}e[N];
int fa[30];
int find(int x){
return fa[x] == x? x : find(fa[x]);
}
int main(){
int n,u,v,tmp;
int num;
char s[2];
while(scanf("%d",&n) && n){
num = 0;
for(int i = 0;i < 30;i++) fa[i] = i;
for(int i = 1;i <= n-1;i++){
scanf("%s%d",s,&tmp);
u = s[0] - 'A';
for(int j = 1;j <= tmp;j++){
scanf("%s%d",s,&e[num].value);
e[num].u = u;
e[num].v = s[0] - 'A';
num++;
}
}
sort(e,e+num);
int ans = 0;
for(int i = 0;i < num;i++){
int x = find(e[i].u);
int y = find(e[i].v);
if(x != y){
fa[x] = fa[y];
ans += e[i].value;
}
}
printf("%d\n",ans);
}
return 0;
}