每个青蛙喝黑茶或者红茶或者都可以喝
M个矛盾关系 有矛盾的不能喝同种茶 但你可以花费Wi使得这个青蛙消除所有矛盾 把矛盾当作边 青蛙当作点 如果这两个青蛙只喝不同的一种茶就不建边
题目中保证了不存在奇环 可以黑白染色成二分图
然后把两个茶都可以喝的青蛙拆点 u表示该青蛙喝黑茶 u+n表示喝红茶 同时建边(u,u+n)
有四种情况:
1.两个青蛙都可以喝两种茶 建边(u,v) (u+n,v+n)
2.两个青蛙一个可以喝两种茶 一个可以喝黑茶 建边(u,v)
3.两个青蛙一个可以喝两种茶 一个可以喝红茶 建边(u,v+n)
4.两种青蛙都只能喝一种茶 建边(u,v)
然后黑白染色成二分图连S,T 跑二分图最小点权覆盖集
最后跑出来的答案要减去sumw 因为两种茶都可以喝的青蛙拆点导致每次拆点多花费了Wi
#include<bits/stdc++.h> using namespace std; const int MAXN = 3050; const int MAXM = 100000; const int INF = 1000000005; int Head[MAXN], cur[MAXN], lev[MAXN], to[MAXM << 1], nxt[MAXM << 1], f[MAXM << 1], ed, S, T; int n, m; inline void addedge(int u, int v, int cap) { to[++ed] = v; nxt[ed] = Head[u]; Head[u] = ed; f[ed] = cap; to[++ed] = u; nxt[ed] = Head[v]; Head[v] = ed; f[ed] = 0; return ; } inline bool BFS() { int u; memset(lev, -1, sizeof(lev)); queue<int> q; lev[S] = 0; q.push(S); while (q.size()) { u = q.front(); q.pop(); for (int i = Head[u]; i; i = nxt[i]) { if (f[i] && lev[to[i]] == -1) { lev[to[i]] = lev[u] + 1; q.push(to[i]); } } } memcpy(cur, Head, sizeof(Head)); return lev[T] != -1; } inline int DFS(int u, int maxf) { if (u == T || !maxf) { return maxf; } int cnt = 0; for (int &i = cur[u], tem; i; i = nxt[i]) { if (f[i] && lev[to[i]] == lev[u] + 1) { tem = DFS(to[i], min(maxf, f[i])); maxf -= tem; f[i] -= tem; f[i ^ 1] += tem; cnt += tem; if (!maxf) { break; } } } if (!cnt) { lev[u] = -1; } return cnt; } int Dinic() { int ans = 0; while (BFS()) { ans += DFS(S, 2147483647); } return ans; } void init(int SS, int TT) { memset(Head, 0, sizeof(Head)); ed = 1; S = SS, T = TT; return ; } struct node { int kind; int id; int l, r; int w; } frog[2005]; vector<int> g[2 * MAXN]; int color[2 * MAXN]; int sumw; void dfs(int x, int pre) { for (int v : g[x]) { if (v == pre || color[v] != -1) { continue; } color[v] = color[x] ^ 1; dfs(v, x); } } inline void add(int u, int v) { g[u].push_back(v); g[v].push_back(u); } int main() { int u, v; while (scanf("%d %d", &n, &m) != -1) { sumw = 0; for (int i = 1; i <= 2 * n; i++) { color[i] = -1; g[i].clear(); } for (int i = 1; i <= n; i++) { scanf("%d", &frog[i].w); } for (int i = 1; i <= n; i++) { scanf("%d", &frog[i].kind); if (frog[i].kind == 3) { sumw += frog[i].w; add(i, i + n); } } for (int i = 1; i <= m; i++) { scanf("%d %d", &u, &v); if (frog[u].kind + frog[v].kind == 3) { continue; } if (frog[u].kind > frog[v].kind) { swap(u, v); } if (frog[u].kind != 3) { if (frog[v].kind != 3) { add(u, v); } else { if (frog[u].kind == 1) { add(u, v); } else { add(u, v + n); } } } else { add(u, v); add(u + n, v + n); } } for (int i = 1; i <= 2 * n; i++) { if (color[i] == -1) { color[i] = 0; dfs(i, -1); } } init(0, 2 * n + 1); for (int i = 1; i <= 2 * n; i++) { int wnow; if (i > n) { wnow = frog[i - n].w; } else { wnow = frog[i].w; } if (color[i] == 0) { addedge(S, i, wnow); } else { addedge(i, T, wnow); } } for (int i = 1; i <= 2 * n; i++) { if (color[i] == 0) { for (int v : g[i]) { addedge(i, v, INF); } } } int anser = Dinic(); anser -= sumw; printf("%d ", anser); } return 0; }