- 传送门 -
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3592
const int N = 1000 + 5;
const int inf = 0x7fffffff;
struct edge {
int x, y, v;
}W[N*N];
int F[N], X[N], Y[N], C[10];
int cnt, cst, ans, n, m, T, sz;
vector
bool cmp (edge a, edge b) { return a.v < b.v; }
int distance(int a, int b) {
return (X[a] - X[b]) * (X[a] - X[b]) + (Y[a] - Y[b]) * (Y[a] - Y[b]);
}
int find(int x) { return F[x] == x ? x : F[x] = find(F[x]); }
int merge(int a, int b) {
int xf = find(a), yf = find(b);
if (xf == yf) return 0;
F[xf] = yf;
cnt ++;
return 1;
}
int kruskal() {
int tot = 0;
for (int i = 1, tmp; i <= sz; ++i) {
tmp = merge(W[i].x, W[i].y);
if (tmp) tot += W[i].v;
if (cnt == n - 1) break; //注意cnt的初始化
}
return tot;
}
void init() {
cnt = cst = 0;
for (int i = 0; i <= n; ++i)
F[i] = i;
}
int main() {
scanf("%d", &T);
for (int cas = 0; cas < T; ++cas) {
if (cas) printf("
"); //uva诡异的输出
sz = cnt = 0;
scanf("%d%d", &n, &m);
for (int i = 0, ct, tmp; i < m; ++i) {
scanf("%d%d", &ct, &C[i]);
S[i].clear();
for (int j = 1; j <= ct; ++j) {
scanf("%d", &tmp);
S[i].push_back(tmp);
}
}
for (int i = 1; i <= n; ++i) {
scanf("%d%d", &X[i], &Y[i]);
for (int j = 1; j < i; ++j) {
W[++sz].x = j; W[sz].y = i;
W[sz].v = distance(i, j);
}
}
sort(W + 1, W + sz + 1, cmp);
init();
ans = kruskal();//不买套餐的情况
for (int i = 1; i < (1 << m); ++i) {
init();//初始化
for (int j = 0; j < m; ++j) {
if (i & (1 << j)) {
for (int k = 1, tmp; k < S[j].size(); ++k)
tmp = merge(S[j][k], S[j][0]);
cst += C[j];
}
}
int aa = kruskal();
ans = min(ans, cst + aa);
}
printf("%d
", ans);
}
}