题面
题解
选某个点就必须选其他的点
最大权闭合子图
Code
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <queue> const int N = 505; const int INF = 0x3f3f3f3f; using namespace std; int n, x[N], y[N], r[N], S, T, cnt = 1, head[N], d[N], cur[N], sum; struct edge { int to, nxt, flow; } e[N * N * 4]; queue<int> q; template < typename T > inline T read() { T x = 0, w = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); } while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * w; } int mabs(int x) { return x > 0 ? x : -x; } inline void adde(int u, int v, int w) { e[++cnt] = (edge) { v, head[u], w }, head[u] = cnt; e[++cnt] = (edge) { u, head[v], 0 }, head[v] = cnt; } bool check(int i, int j) { return mabs(x[i] - x[j]) * mabs(x[i] - x[j]) + mabs(y[i] - y[j]) * mabs(y[i] - y[j]) <= r[i] * r[i]; } bool bfs() { memset(d, 0, sizeof(d)), d[S] = 1, q.push(S); while(!q.empty()) { int u = q.front(); q.pop(); for(int v, i = head[u]; i; i = e[i].nxt) { v = e[i].to; if(!d[v] && e[i].flow > 0) d[v] = d[u] + 1, q.push(v); } } return d[T]; } int dfs(int u, int a) { if(u == T || !a) return a; int f = 0; for(int v, &i = cur[u]; i; i = e[i].nxt) { v = e[i].to; if(e[i].flow > 0 && d[v] == d[u] + 1) { int tmp = dfs(v, min(a, e[i].flow)); f += tmp, a -= tmp, e[i].flow -= tmp, e[i ^ 1].flow += tmp; } if(!a) break; } if(a) d[u] = 0; return f; } int dinic() { int flow = 0; while(bfs()) memcpy(cur, head, sizeof(cur)), flow += dfs(S, INF); return flow; } int main() { n = read <int> (), S = n + 1, T = S + 1; for(int k, i = 1; i <= n; i++) { x[i] = read <int> (), y[i] = read <int> (), r[i] = read <int> (); k = read <int> (); if(k > 0) sum += k, adde(S, i, k); else adde(i, T, -k); } for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) if(i != j && check(i, j)) adde(i, j, INF); printf("%d\n", sum - dinic()); return 0; }
来源:https://www.cnblogs.com/ztlztl/p/12296686.html