[Bzoj 3438] Crop of little M

3438: Little M's Crop

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 1780  Solved: 753
[Submit][Status][Discuss]

Description

Small M has opened up two huge arable fields A and B in MC (you can think that the capacity is infinite), now, small P has the seeds of n crops, the seeds of each crop
There is 1 (that is, a crop can be planted) (numbered with 1...n), now, the i-th crop can be planted in A to get the benefits of ai, and planted in B
You can get the benefits of bi, and now there is such a magical phenomenon, that is, some crops can be jointly planted in a piece of arable land to get additional benefits
, Xiao M found a total of m crop combinations in the rule, the crops in the i-th combination can be planted together in A to obtain additional income of c1i, and the total amount of crops in B can be
Get the extra income of c2i, so Xiao M quickly calculated the maximum income of planting, but he wants to test you, can you answer his question?

Input

The first line contains an integer n
The second line includes n integers, indicating ai The third line includes n integers, indicating that the bi fourth line includes an integer m followed by m lines,
For the next i-th row: the first integer ki, indicating that there are ki crops in the i-th crop combination,
The next two integers c1i, c2i, followed by ki integers, represent the crop number in the combination. output format

Output

There is only one line, including an integer, representing the maximum gain

Range

1<= k< n <= 1000,0 < m <= 1000 All data and results are guaranteed not to exceed 2*10^9.

Solution

good question~

At first, the cost flow result I thought would ask for a lot of answers. After reading the solution, I knew it was related to the minimum cut.

We take the source point as the A field and the sink point as the B field.

For crop i, if the value planted in A is a[i] and the value planted in B is b[i], then connect an edge with capacity a[i] from it to A. Similarly, connect to B. An edge of capacity b[i].

Why do you do that? Considering the last answer, one of the two sides connected by a point must be cut off. Otherwise, the point is connected to both sides, which is equivalent to planting on both sides, which does not meet the meaning of the question, so this situation does not meet the meaning of the question.

There must be one that will be cut... Hey, isn't this the smallest cut?

Then we have initially transformed the problem, that is, we have transformed the problem into the minimum cut.

Next, consider the question of composition.

In fact, the combination is also the same, that is, the combination is also divided into two parts, which are connected to A and B.

Take this set apart first. Then the incoming edge of one of the points is connected to A, and the capacity is the extra value of the combination planted in A, and the outgoing edge is connected to all the points in this combination, and the capacity is INF. B is the same.

Then we have completely transformed the problem into the minimum cut. But this question wants to make ans the biggest, what should we do?

Well, just add up the total returns and subtract the minimum cut.

Code

// By YoungNeal
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#define N 10005
#define inf 0x3f3f3f3f-1

you are everything;
int d [N];
int cnt = 1 ;
int dis [N];
int head [N];
int n, m, s, t;

struct Edge{
    int to,nxt,flow;
}edge[4400000];

void add(int x,int y,int z){
    edge[++cnt].to=y;
    edge[cnt].nxt=head[x];
    edge[cnt].flow=z;
    head[x]=cnt;
}

bool bfs(){
    memset(d,0,sizeof d); d[s]=1;
    std::queue<int> q; q.push(s);
    while(q.size()){
        int u=q.front();q.pop();
        for(int i=head[u];i;i=edge[i].nxt){
            int to=edge[i].to;
            if(!edge[i].flow) continue;
            if(d[to]) continue;
            d[to]=d[u]+1;
            q.push(to);
            if(to==t) return 1;
        }
    }
    return 0;
}

int dinic(int now,int flow){
    if(now==t) return flow;
    int rest=flow;
    for(int i=head[now];i;i=edge[i].nxt){
        if(!rest) return flow;
        int to=edge[i].to;
        if(!edge[i].flow) continue;
        if(d[to]!=d[now]+1) continue;
        int k=dinic(to,std::min(rest,edge[i].flow));
        if(!k) d[to]=0;
        rest-=k;
        edge[i].flow-=k;
        edge[i^1].flow+=k;
    }
    return flow-rest;
}

signed main(){
    scanf("%d",&n); s=n+1; t=s+1;
    for(int x,i=1;i<=n;i++) scanf("%d",&x),tot+=x,add(s,i,x),add(i,s,0);
    for(int x,i=1;i<=n;i++) scanf("%d",&x),tot+=x,add(i,t,x),add(t,i,0);
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
        int T,tota,totb;
        scanf("%d%d%d",&T,&tota,&totb);
        tot + = tota + totb;
        add(s,n+2+i,tota); add(n+2+i,s,0);
        add(n+2+i+m,t,totb); add(t,n+2+i+m,0);
        for(int x,j=1;j<=T;j++){
            scanf("%d",&x);
            add(n+2+i,x,inf);
            add(x,n+2+i,0);
            add(x,n+2+i+m,inf);
            add(n+2+i+m,x,0);
        }
    }
    int maxflow=0,flow=0;
    while(bfs()) 
        while(flow=dinic(s,0x3f3f3f3f)) maxflow+=flow;
    printf("%d\n",tot-maxflow);
    return 0;
}

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324494255&siteId=291194637