UVa 1151 Buy or Build (最小生成樹)
阿新 • • 發佈:2021-07-08
題目連結
先求出不買套餐的最小生成樹的邊
然後列舉選擇哪些套餐,將套餐中的邊權置為 \(0\), 和原先最小生成樹的邊重新進行 \(kruscal\)
而原先選不到的邊,權值大於套餐和最小生成樹的邊,後來一定也選不到
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1000100; const int INF = 1000000007; int T, n, q, cnt, ans; int c[10]; int x[maxn], y[maxn]; vector<int> Gc[10]; struct Edge{ int u, v, w; bool operator < (const Edge& o) const{ return w < o.w; } }e[maxn]; vector<Edge> E, nE; int par[maxn], ran[maxn]; int find(int x){ return par[x] == x ? x : par[x] = find(par[x]); } void unite(int x, int y){ x = find(x), y = find(y); if(x == y) return; if(ran[x] < y){ par[x] = y; } else{ par[y] = x; if(ran[x] == ran[y]) ++ran[x]; } } void kruscal(){ for(int i = 1 ; i <= n ; ++i) par[i] = i, ran[i] = 1; int tot = 0; for(int i = 1 ; i <= cnt ; ++i){ if(find(e[i].u) != find(e[i].v)){ unite(e[i].u, e[i].v); ++tot; E.push_back(e[i]); if(tot == n - 1){ break; } } } } int use[maxn]; void dfs(int d){ if(d == q + 1){ nE.clear(); int res = 0; for(auto u : E){ nE.push_back(u); } for(int i = 1 ; i <= q ; ++i){ if(use[i]){ res += c[i]; int u = -1; for(auto v : Gc[i]){ Edge ne; if(u != -1){ ne.u = u; ne.v = v; ne.w = 0; nE.push_back(ne); u = v; } else{ u = v; } } } } sort(nE.begin(), nE.end()); for(int i = 1 ; i <= n ; ++i) par[i] = i, ran[i] = 1; int tot = 0; for(auto p : nE){ if(find(p.u) != find(p.v)){ unite(p.u, p.v); ++tot; res += p.w; if(tot == n - 1){ ans = min(ans, res); break; } } } return; } use[d] = 1; dfs(d + 1); use[d] = 0; dfs(d + 1); } ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; } int main(){ scanf("%d", &T); int flag = 0; while(T--){ if(flag){ printf("\n"); } flag = 1; cnt = 0; for(int i = 1 ; i <= q ; ++i) Gc[i].clear(); E.clear(); memset(use, 0, sizeof(use)); ans = INF; scanf("%d%d", &n, &q); for(int i = 1 ; i <= q ; ++i){ int u, v; scanf("%d", &u); scanf("%d", &c[i]); for(int j = 1 ; j <= u ; ++j){ scanf("%d", &v); Gc[i].push_back(v); } } for(int i = 1 ; i <= n ; ++i){ scanf("%d%d", &x[i], &y[i]); } for(int i = 1 ; i <= n ; ++i){ for(int j = i + 1 ; j <= n ; ++j){ ++cnt; e[cnt].u = i, e[cnt].v = j; e[cnt].w = (x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]); } } sort(e + 1, e + 1 + cnt); kruscal(); dfs(1); printf("%d\n", ans); } return 0; }