//UVA1151BuyOrBuild
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxq = 8 + 2;
const int maxn = 1000 + 10;
int cost[maxq], x[maxn], y[maxn], p[maxn];
int n, q;
vector<int> subq[maxq];
struct Edge {
int u, v, c;
Edge(int u, int v, int c) : u(u), v(v), c(c) {}
bool operator < (const Edge& rhs) const {
return c < rhs.c;
}
};
int findset(int x) {
return x == p[x] ? x : findset(p[x]);
}
int MST(int cnt, const vector<Edge>& e) {
int m = e.size(), spend = 0;
for(int i = 0; i < m; i++) {
int x = findset(e[i].u), y = findset(e[i].v);
if(x != y) {
p[x] = y;
spend += e[i].c;
if(--cnt == 1) return spend;
}
}
return 0;
}
int main() {
int T;
scanf("%d", &T);
while(T--) {
int cnt;
scanf("%d%d", &n, &q);
for(int i = 0; i < q; i++) {
scanf("%d%d", &cnt, &cost[i]);
subq[i].clear();
for(int j = 0; j < cnt; j++) {
int id; scanf("%d", &id);
subq[i].push_back(id - 1);
}
}
vector<Edge> e;
for(int i = 0; i < n; i++)
scanf("%d%d", &x[i], &y[i]);
for(int i = 0; i < n; i++)
for(int j = i + 1; j < n; j++) {
int c = (x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]);
e.push_back(Edge(i, j, c));
}
cnt = n;
sort(e.begin(), e.end());
for(int i = 0; i < n; i++) p[i] = i;
int ans = MST(cnt, e);
for(int subset = 1; subset < (1 << q) - 1; subset++) {
cnt = n;
int spend = 0;
for(int i = 0; i < n; i++) p[i] = i;
for(int i = 0; i < q; i++) if(subset & (1 << i)) {
spend += cost[i];
for(int j = 0; j < subq[i].size(); j++) {
int x = findset(subq[i][j]), y = findset(subq[i][0]);
if(x != y) {
p[x] = y;
cnt--;
}//对每一种已选择的连通分量,构建并查集
}
}
ans = min(ans, spend + MST(cnt, e));
}
printf("%d\n", ans);
if(T) printf("\n");
}
return 0;
}
/*
1
7 3
2 4 1 2
3 3 3 6 7
3 9 2 4 5
0 2
4 0
2 0
4 2
1 3
0 5
4 4
*/
UVA1151BuyOrBuild
最新推荐文章于 2022-04-01 10:11:35 发布