题意:
输入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
考试周还在敲代码...我...
update:最近复习模板,蓝桥杯不给带模板TAT,顺手A了Prim做法。
代码:
/*Prim*/ #include<set> #include<map> #include<stack> #include<cmath> #include<queue> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> typedef long long ll; using namespace std; const int maxn = 500 + 10; const int seed = 131; const ll MOD = 100000007; const int INF = 0x3f3f3f3f; int mp[maxn][maxn]; int dis[maxn], vis[maxn], pre[maxn], n, ans; void init(){ scanf("%d", &n); memset(vis, 0, sizeof(vis)); for(int i = 1; i <= n; i++){ for(int j = 1; j <= n; j++){ scanf("%d", &mp[i][j]); } } vis[1] = 1; for(int i = 2; i <= n; i++){ dis[i] = mp[1][i]; pre[i] = 1; } } void prim(){ ans = 0; for(int i = 1; i <= n - 1; i++){ int pos, Min = INF; for(int j = 1; j <= n; j++){ if(!vis[j] && dis[j] < Min){ pos = j; Min = dis[j]; } } vis[pos] = 1; ans = max(ans, mp[pos][pre[pos]]); for(int j = 1; j <= n; j++){ if(!vis[j] && mp[j][pos] < dis[j]){ dis[j] = mp[j][pos]; pre[j] = pos; } } } } int main(){ int t, n; scanf("%d", &t); while(t--){ init(); prim(); printf("%d\n", ans); } return 0; }
代码:
#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; }