有 n 個城市(n ≤ 1000)和 q 個現有子網絡(q ≤ 8)。每個子網絡包含若干城市,購買成本固定,不可拆分。若不購買子網絡,任兩城市間建邊成本為歐氏距離平方。求連接所有城市的最小總成本。
題目連結:POJ 2784
由於 q ≤ 8,子網絡購買組合最多 2^8 = 256 種,可用狀態壓縮枚舉所有購買方案:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 1009;
int fa[N], x[N], y[N];
int cost[9], mcnt[9], sub[9][N];
int n, q;
struct Edge { int u, v; double w; };
bool operator<(Edge a, Edge b) { return a.w < b.w; }
int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
double kruskal() {
vector edges;
for (int i = 1; i <= n; i++)
for (int j = i+1; j <= n; j++)
if (find(i) != find(j)) {
double dx = x[i]-x[j], dy = y[i]-y[j];
edges.push_back({i, j, dx*dx + dy*dy});
}
sort(edges.begin(), edges.end());
double sum = 0;
for (auto &e : edges) {
int fu = find(e.u), fv = find(e.v);
if (fu != fv) {
fa[fu] = fv;
sum += e.w;
}
}
return sum;
}
int main() {
while (cin >> n >> q) {
for (int i = 1; i <= q; i++) {
cin >> mcnt[i] >> cost[i];
for (int j = 1; j <= mcnt[i]; j++) cin >> sub[i][j];
}
for (int i = 1; i <= n; i++) cin >> x[i] >> y[i];
double ans = 1e18;
for (int mask = 0; mask < (1<
複雜度分析
枚舉 2^q 種方案,每次 Kruskal 處理 O(n^2 log n) 邊。總複雜度 O(2^q × n^2 log n),q ≤ 8 時可行。


