BZOJ3438 小M的作物 (最小割)
作者:互联网
BZOJ3438 小M的作物 (最小割)
模型:二者取一,体现为把点集一分为二。
源点向所有作物连边,流量为ai
所有作物向汇点连边,流量为bi
对于每组作物,新建两个点
源点向点1连一条流量为c1i的边,点2向汇点连一条流量为c2i的边
点1点2分别与组内作物连流量为inf的边
对于一个割,每个作物与源点联通代表种在A地,否则种在B地,需要割去另一部分的收益
如果组内的点不都与源点联通,则c1i必被割掉
c2i亦是如此
所以答案为总收益-最小割
卡普通Dinic,加一个弧优化既可以过了.
// luogu-judger-enable-o2
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
const int maxN = 3000 + 7;
const int maxM = 5000000 + 7;
const int inf = 1e9;
int n , m, s, t;
inline int gi() {
int x = 0,f = 1;char c = getchar();
while(c < '0' || c > '9'){if(c == '-')f = -1;c = getchar();}
while(c >= '0' && c <= '9'){x = x * 10 + c - '0';c = getchar();}
return x * f;
}
struct Node {
int v,w,nex;
}Map[maxM];
int head[maxN] , dep[maxN], num = 1, cnr[maxN];
inline void add_Node(int u , int v, int w) {
Map[++ num] = (Node) {v , w, head[u]};head[u] = num;
Map[++ num] = (Node) {u , 0, head[v]};head[v] = num;
}
int sum;
bool bfs() {
memset(dep , 0, sizeof(dep));dep[s] = 1;
memcpy(cnr,head,sizeof(head));
queue<int>q;q.push(s);
do {
int u = q.front();
q.pop();
for(register int i = head[u];i;i = Map[i].nex) {
int v = Map[i].v;
if(Map[i].w && !dep[v]) {
dep[v] = dep[u] + 1;
q.push(v);
if(v == t) return true;
}
}
}while(!q.empty());
return false;
}
int dfs(int now,int dist) {
if(now == t)return dist;
int nowflow = 0;
for(register int i = cnr[now] ;i;i = Map[i].nex) {
int v = Map[i].v;
cnr[now]=i;
if(dep[v] == dep[now] + 1 && Map[i].w) {
int di = dfs(v,min(dist,Map[i].w));
Map[i].w -= di;
Map[i ^ 1].w += di;
nowflow += di;
dist -= di;
if(!dist) break;
}
}
return nowflow;
}
inline int Dinic() {
int Ans = 0;
while(bfs()) {
while(int d = dfs(s,inf))
Ans += d;
}
return Ans;
}
int main() {
n = gi(); s = n + 1;t = s + 1;
for(register int i = 1;i <= n;++ i) {int w = gi();add_Node(s , i, w);sum += w;}
for(register int i = 1;i <= n;++ i) {int w = gi();add_Node(i, t, w);sum += w;}
m = gi();
for(register int i = 1;i <= m;++ i) {
int k = gi() , c1 = gi(), c2 = gi();sum = sum + c1 + c2;
add_Node(s , n + 2 + i, c1);
add_Node(n + m + 2 + i , t, c2);
for(register int j = 1;j <= k;++ j) {
int v = gi();
add_Node(n + 2 + i, v, inf);
add_Node(v , n + 2 + i + m, inf);
}
}
printf("%d" , sum - Dinic());
return 0;
}
标签:Map,now,dist,di,int,最小,return,BZOJ3438,作物 来源: https://www.cnblogs.com/gzygzy/p/10361046.html