NYOJ-1239-引水工程

xiaoxiao2021-02-27  524

ACM模版

描述

题解

这个题用最小生成树的两个经典算法都可以过,用 Prim 算法相对容易写,只要再不断扩展的过程中判定究竟是建站消耗高还是建管道高,如果用 Kruskal 算法的话,则需要在生成最小树的过程中存树,然后 dfs 一遍做和前者同样的判定即可。

我用的是第二种,但是其实 Kruskal 算法还有更简单的解法,只消建一个超级源点即可,将所有站的建站消费都转化为边权连在超级源点上即可。

代码

#include <iostream> #include <algorithm> #include <vector> #include <cstring> #include <cstdio> using namespace std; const int INF = 0x3f3f3f3f; const int MAXN = 333; const int MAXM = 1e5; int map[MAXN][MAXN]; vector<int> tree[MAXN]; int F[MAXN]; struct Edge { int u; int v; int w; } edge[MAXM]; int tol; int vis[MAXN]; void init() { tol = 0; for (int i = 0; i < MAXN; i++) { tree[i].clear(); } memset(vis, 0, sizeof(vis)); } void addEdge(int u, int v, int w) { edge[tol].u = u; edge[tol].v = v; edge[tol++].w = w; } bool cmp(Edge a, Edge b) { return a.w < b.w; } int find(int x) { if (F[x] == x) { return x; } else { return F[x] = find(F[x]); } } int Kruskal(int n) { for (int i = 0; i <= n; i++) { F[i] = i; } sort(edge, edge + tol, cmp); int cnt = 0; int ans = 0; for (int i = 0; i < tol; i++) { int u = edge[i].u; int v = edge[i].v; int w = edge[i].w; int tOne = find(u); int tTwo = find(v); if (tOne != tTwo) { ans += w; F[tOne] = tTwo; cnt++; tree[u].push_back(v); tree[v].push_back(u); } if (cnt == n - 1) { break; } } if (cnt < n - 1) { return -1; } else { return ans; } } int ans; int value[MAXN]; void dfs(int root) { for (int i = 0; i < tree[root].size(); i++) { int tmp = tree[root][i]; if (!vis[tmp]) { vis[tmp] = 1; if (value[tmp] < map[root][tmp]) { ans += value[tmp] - map[root][tmp]; } dfs(tmp); } } } int main() { int K; cin >> K; int N; while (K--) { init(); cin >> N; int minValue = INF; int root = -1; for (int i = 0; i < N; i++) { cin >> value[i]; if (value[i] < minValue) { minValue = value[i]; root = i; } } vis[root] = 1; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { cin >> map[i][j]; if (i != j) { addEdge(i, j, map[i][j]); } } } ans = Kruskal(N); ans += minValue; dfs(root); cout << ans << '\n'; } return 0; }
转载请注明原文地址: https://www.6miu.com/read-647.html

最新回复(0)