Codeforces 311E Biologist

The first minimum cut I wrote

Choose one from two, consider a fishbone type drawing (your own name), and then use the minimum cut to find the minimum cost.

Fishbone mapping is about a row of points in the middle, and then \ (S \) on the left is connected to this row of points, and this row of points is connected to \ (T \) on the right, which looks like fishbone (?)

trick: maximum value = total value - Minimum Cost

If this position is \ (0 \), the source point \ (S \) is connected to an edge with a flow of \ (v \). If it exists, it means \ (0 \) is selected. If it is cut off, it means the cost of \ (v \) is spent, and it is \ (1 \); If this position is \ (1 \), it is connected to an edge of the sink \ (T \) with a flow of \ (v \). If it exists, it means \ (1 \) is selected. If it is cut off, it means the cost of \ (v \) is spent, and it is \ (0 \)

First of all, this \ (g \) is useless. If the 25-year-old wants to lose money, add \ (W \) and \ (g \), and then subtract \ (g \) from the total answer.

Now the limit is: if you choose \ (0 / 1 \) in all these positions, you can mention the value of \ (W \). Corresponding to the minimum cut: first assume that the conditions are met to obtain the value of \ (W \); If one of the \ (1 / 0 \) points and \ (T/S \) edges of these positions is not cut off, it will cost \ (W \).

Then create a new point \ (x \), if all the restricted positions are selected \ (0 \), even \ ((x,\text {restricted position}, + \ infty) \), \ ((S,x,W) \), that is, the point \ (x \) is in part of the point \ (0 \) in the bipartite graph. The same is true if it selects all the restricted positions \ (1 \), except that it is in part with the \ (1 \) point in the bipartite graph.

Perceptually understand why such a minimum cut is the minimum cost: suppose it restricts several positions to \ (0 \), if some positions were originally filled with \ (1 \), then if the edge of that position connected to \ (T \) is not cut off and does not meet the limit, \ ((S,x,W) \) must be cut off, which is in line with the meaning of the question; If some positions are filled with \ (0 \), if the edge corresponding to this position \ (P \) is cut off, in the minimum cut, at least one limit \ (Y \) can be reached from it, so that the flow can flow through \ (S\to x\to p\to y\to T \). In this way, only the edge of \ (S\to x \) can be cut (if all \ (y\to T \) are cut off), Then \ (S\to p \) must not be cut off, because if it is cut off, it is not excellent), so \ ((S,x,W) \) must be cut off, which is in line with the meaning of the question.

As for the side where \ (0 \) traffic may occur, it is actually irrelevant (?)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#define pb emplace_back
#define mp std::make_pair
#define fi first
#define se second
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef std::pair<int, int> pii;
typedef std::vector<int> vi;
const ll mod = 998244353;
ll Add(ll x, ll y) { return (x+y>=mod) ? (x+y-mod) : (x+y); }
ll Mul(ll x, ll y) { return x * y % mod; }
ll Mod(ll x) { return x < 0 ? (x + mod) : (x >= mod ? (x-mod) : x); }
ll cadd(ll &x, ll y) { return x = (x+y>=mod) ? (x+y-mod) : (x+y); }
ll cmul(ll &x, ll y) { return x = x * y % mod; }
template <typename T> T Max(T x, T y) { return x > y ? x : y; }
template<typename T, typename... T2> T Max(T x, T2 ...y) { return Max(x, y...); }
template <typename T> T Min(T x, T y) { return x < y ? x : y; }
template<typename T, typename... T2> T Min(T x, T2 ...y) { return Min(x, y...); }
template <typename T> T cmax(T &x, T y) { return x = x > y ? x : y; }
template <typename T> T cmin(T &x, T y) { return x = x < y ? x : y; }
template <typename T>
T &read(T &r) {
	r = 0; bool w = 0; char ch = getchar();
	while(ch < '0' || ch > '9') w = ch == '-' ? 1 : 0, ch = getchar();
	while(ch >= '0' && ch <= '9') r = r * 10 + (ch ^ 48), ch = getchar();
	return r = w ? -r : r;
}
template<typename T1, typename... T2>
void read(T1 &x, T2& ...y) { read(x); read(y...); }
const int N = 100010;
const int M = 500010;
const ll INF = 0x7fffffffffffffff;
int n, m, g;
int a[N], v[N];
int tot, S, T, ent = 1, head[N], cur[N], dis[N];
struct Edge {
	int to, nxt;
	ll fl;
}e[M << 1];
inline void add(int x, int y, ll z) {
	//printf("%d %d %d\n", x, y, z);
	e[++ent].to = y; e[ent].fl = z; e[ent].nxt = head[x]; head[x] = ent;
	e[++ent].to = x; e[ent].fl = 0; e[ent].nxt = head[y]; head[y] = ent;
}
bool bfs() {
	for(int i = 1; i <= tot; ++i) dis[i] = -1, cur[i] = head[i];
	std::queue<int>q;
	q.push(S); dis[S] = 0;
	while(!q.empty()) {
		int x = q.front(); q.pop();
		for(int i = head[x]; i; i = e[i].nxt) {
			int v = e[i].to;
			if(dis[v] == -1 && e[i].fl) {
				dis[v] = dis[x] + 1;
				q.push(v);
			}
		}
	}
	return dis[T] != -1;
}
ll dfs(int x, ll lim) {
	if(x == T) return lim;
	ll flow = 0;
	for(int i = cur[x]; i && flow < lim; i = e[i].nxt) {
		int v = e[i].to; cur[x] = i;
		if(dis[v] == dis[x] + 1 && e[i].fl) {
			ll f = dfs(v, Min(e[i].fl, lim - flow));
			flow += f; e[i].fl -= f; e[i^1].fl += f;
		}
	}
	return flow;
}
ll dinic() {
	ll mxfl = 0;
	while(bfs())
		mxfl += dfs(S, INF);
	return mxfl;
}
signed main() { //freopen("data.in", "r", stdin);
	ll sum = 0;
	read(n, m, g); tot = n; S = ++tot; T = ++tot;
	for(int i = 1; i <= n; ++i) read(a[i]);
	for(int i = 1; i <= n; ++i) read(v[i]);
	for(int i = 1; i <= n; ++i) {
		if(!a[i]) add(S, i, v[i]);
		else add(i, T, v[i]);
	}
	for(int i = 1; i <= m; ++i) {
		int p = ++tot, to, W, k, f; read(to, W, k); vi vec;
		for(int j = 1, x; j <= k; ++j) {
			read(x);
			if(!to) add(p, x, INF);
			else add(x, p, INF);
		}
		read(f);
		if(f) W += g, sum -= g;
		sum += W;
		if(!to) add(S, p, W);
		else add(p, T, W);
	}
	printf("%lld\n", sum - dinic());
	return 0;
}

Keywords: network-flows

Added by Dark[NSF] on Wed, 19 Jan 2022 01:22:56 +0200