您的位置:首页 > 产品设计 > UI/UE

UVa1151 Buy or Build

2016-01-08 15:10 411 查看
填坑(p.358)

以前天真的以为用prim把n-1条边求出来就可以

现在看来是我想多了

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>

const int N = 1000 + 10;

struct Node {
int x, y;
Node(int x = 0, int y = 0) : x(x), y(y) {}
}p
;

int sqr(int x) {
return x * x;
}

int dist(const Node& a, const Node& b) {
return sqr(a.x - b.x) + sqr(a.y - b.y);
}

struct Edge {
int u, v, w;
Edge() {}
Edge(int u, int v, int w) : u(u), v(v), w(w) {}
bool operator < (const Edge& rhs) const {
return w < rhs.w;
}
};
#include<vector>
std::vector<Edge> edges, pree;

int n, ans;
int d
, pre
, dis

;
bool inMST
;

void prim() {
memset(d, 0x3f, sizeof d);
memset(inMST, 0, sizeof inMST);
ans = d[0] = 0;
for(int i = 0; i < n; i++) {
int u = -1;
for(int v = 0; v < n; v++) if(!inMST[v]) {
if(u == -1 || d[v] < d[u]) u = v;
}
inMST[u] = 1;
ans += d[u];
if(i) edges.push_back(Edge(u, pre[u], dis[u][pre[u]]));
for(int v = 0; v < n; v++) if(!inMST[v]) {
if(d[v] > d[u] + dis[u][v]) {
d[v] = d[u] + dis[u][v];
pre[v] = u;
}
}
}
}

int fa
;
int find(int x) {
return fa[x] == x ? x : fa[x] = find(fa[x]);
}

bool merge(int x, int y) {
x = find(x), y = find(y);
if(x == y) return 0;
return fa[x] = y, 1;
}

void UFS_init() {
for(int i = 0; i < n; i++) fa[i] = i;
}

void pre_kruskal() {
for(int i = 0; i < n; i++) {
for(int j = i + 1; j < n; j++) {
pree.push_back(Edge(i, j, dis[i][j]));
}
}
sort(pree.begin(), pree.end());

UFS_init();
int MST = n;
ans = 0;
for(unsigned i = 0; i < pree.size(); i++) {
const Edge& e = pree[i];
if(merge(e.u, e.v)) {
edges.push_back(e);
ans += e.w;
if(--MST == 1) break;
}
}
}

int q;
#include<vector>
std::vector<int> frees[10];
int cost[10];
#include<cassert>
void Kruskal(int mask) {
UFS_init();
int MST = n, res = 0;
for(int j = 0; j < q; j++) if(mask >> j & 1) {
res += cost[j];
for(unsigned i = 1; i < frees[j].size(); i++) {
MST -= merge(frees[j][i-1], frees[j][i]);
}
}

for(unsigned i = 0; i < edges.size(); i++) {
if(MST == 1) break;
if(merge(edges[i].u, edges[i].v)) res += edges[i].w, MST--;
}
assert(MST == 1);
ans = std::min(ans, res);
}

int main() {
#ifdef DEBUG
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif

int T; scanf("%d", &T);
while(T--) {
pree.clear();
edges.clear();
scanf("%d%d", &n, &q);
for(int i = 0; i < q; i++) {
int m;
scanf("%d%d", &m, cost + i);
frees[i].resize(m);
for(int j = 0; j < m; j++) {
scanf("%d", &frees[i][j]);
--frees[i][j];
}
}
for(int i = 0; i < n; i++) {
scanf("%d%d", &p[i].x, &p[i].y);
for(int j = 0; j < i; j++) {
dis[i][j] = dis[j][i] = dist(p[i], p[j]);
}
}
pre_kruskal();
std::sort(edges.begin(), edges.end());
for(int mask = 0; mask < (1 << q); mask++) {
Kruskal(mask);
}

printf("%d\n", ans);
if(T) puts("");
}

return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: