传送门
题意: 建立一些基站有费用, 然后有m个连接关系, 那就是第i个人需要使用ai, bi 基站进行通信, 同时公司有ci的获利, 问公司最大获利是多少.
思路: 很明显的依赖关系, 基站为点, 人也为点, 如果需要ai, bi, 基站, 那就向对应基站连边即可, 所以就是很明显的最大权闭合子图. 建出相应的模型, 然后用网络流求解即可.
AC Code
const int maxn = 6e4 + 5;
int cnt ;
int n, m, s, t;
bool vis[maxn];
int d[maxn], cur[maxn];
struct Edge {
int u, v;
int cap, flow;
} e[maxn*10]; //因为是双向边 所以记得开二倍
vector<int> G[maxn];
void init() {
cnt = 0;
for (int i = 1 ; i <= n ; i ++) G[i].clear();
}
void add(int u, int v, int cap, int f) {
e[cnt] = Edge{u, v, cap, f};
}
void AddEdge(int u, int v, int cap) {
add(u, v, cap, 0);
G[u].push_back(cnt++);
add(v, u, 0, 0);
G[v].push_back(cnt++);
}
bool BFS() {
Fill(vis, 0);
queue<int> q; q.push(s);
vis[s] = 1; d[s] = 0;
while (!q.empty()) {
int v = q.front(); q.pop();
for (int i = 0; i < G[v].size(); i++) {
Edge &te = e[G[v][i]];
if (!vis[te.v] && te.cap > te.flow) { //只考虑残量网络的弧
vis[te.v] = 1;
d[te.v] = d[v] + 1;
q.push(te.v);
}
}
}
return vis[t];
}
int dfs(int x, int a) {
if (x == t || a == 0) return a;
int flow = 0, f;
for (int &i = cur[x]; i < G[x].size(); i++) { //从上次考虑的弧
Edge &te = e[G[x][i]];
if (d[x] + 1 == d[te.v] && (f = dfs(te.v, min(a, te.cap - te.flow))) > 0) {
te.flow += f;
e[G[x][i]^1].flow -= f;
flow += f;
a -= f;
if (a == 0) break;
}
}
return flow;
}
int Dinic() {
int flow = 0;
while (BFS()) {
Fill(cur, 0);
flow += dfs(s, inf);
}
return flow;
}
void solve() {
scanf("%d%d", &n, &m);
init(); s = 0, t = n + m + 1;
for (int i = 1 ; i <= n ; i ++) {
int x; scanf("%d", &x);
AddEdge(i, t, x);
}
int ans = 0;
for (int i = 1 ; i <= m ; i ++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
AddEdge(i+n, u, w);
AddEdge(i+n, v, w);
AddEdge(s, i+n, w);
ans += w;
}
printf("%d\n", ans - Dinic());
}