题目传送:蓝桥杯 - 安慰奶牛
思路:先算好边的权值,为本来的边的权值的两倍加上两个点的权值,再进行kruskal,因为边数较大,不宜采用prim
AC代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define LL long long #define INF 0x7fffffff const int maxn = 100005; int pa[maxn]; int val[maxn]; int n, m, sum; struct node { int u, v, val; bool operator < (const node& a) const { return val < a.val; } }edge[maxn]; int find(int x) { return x == pa[x] ? x : pa[x] = find(pa[x]); } void add(int u, int v, int pri) { edge[sum].u = u; edge[sum].v = v; edge[sum].val = val[u] + val[v] + pri * 2; sum ++; } void kruscal() { for(int i = 1; i <= n; i++) { pa[i] = i; } int ans = 0; for(int i = 0; i < sum; i++) { int u = edge[i].u; int v = edge[i].v; int pu = find(u), pv = find(v); if(pu == pv) continue; ans += edge[i].val; pa[pu] = pv; } int mi = INF; for(int i = 1; i <= n; i++) { mi = min(mi, val[i]); } printf("%d\n", ans + mi); } int main() { while(scanf("%d %d", &n, &m) != EOF) { sum = 0; for(int i = 1; i <= n; i++) { scanf("%d", &val[i]); } for(int i = 0; i < m; i++) { int u, v, pri; scanf("%d %d %d", &u, &v, &pri); add(u, v, pri); } sort(edge, edge + sum); /*for(int i = 0; i < sum; i++) { printf("%d %d %d\n", edge[i].u, edge[i].v, edge[i].val); }*/ kruscal(); } return 0; }
时间: 2024-10-10 01:05:01