bzoj 3438: 小M的作物

Description

 背景

    小M还是个特么喜欢玩MC的孩纸。。。

 描述

    小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物的种子,每种作物的种子有1个(就是可以种一棵作物)(用1...n编号),现在,第i种作物种植在A中种植可以获得ai的收益,在B中种植可以获得bi的收益,而且,现在还有这么一种神奇的现象,就是某些作物共同种在一块耕地中可以获得额外的收益,小M找到了规则中共有m种作物组合,第i个组合中的作物共同种在A中可以获得c1i的额外收益,共同总在B中可以获得c2i的额外收益,所以,小M很快的算出了种植的最大收益,但是他想要考考你,你能回答他这个问题么?

Input

    第一行包括一个整数n

    第二行包括n个整数,表示ai

    第三行包括n个整数,表示bi

    第四行包括一个整数m

    接下来m行,对于接下来的第i行:第一个整数ki,表示第i个作物组合中共有ki种作物,接下来两个整数c1i,c2i,接下来ki个整数,表示该组合中的作物编号。输出格式

Output

   只有一行,包括一个整数,表示最大收益

Sample Input

3
4 2 1
2 3 2
1
2 3 2 1 2

Sample Output

11
样例解释
A耕地种1,2,B耕地种3,收益4+2+3+2=11。
数据范围与约定
对于100%的数据,1<=k< n<= 1000,0 < m < = 1000 保证所有数据及结果不超过2*10^9。
 
网络流问题
新建源点S表示种在A地的作物,汇点T表示种在B地的作物,其他按照题意连边即可
#include<bits/stdc++.h>
#define inf 0x7fffffff
using namespace std;
inline int read(){
    int s=0;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar());
    for(;ch>='0'&&ch<='9';ch=getchar())s=s*10+ch-'0';
    return s;
}
int n,m;
struct node{
    int to,next;
    int cap,flow;
}G[2000010];
int tot=1,h[10010];
int vis[10010];
int S,T,cnt;
int sum;
void add(int x,int y,int z){
    tot++;G[tot].to=y;G[tot].next=h[x];G[tot].cap=z;h[x]=tot;
}
void ins(int x,int y,int z){
    add(x,y,z);add(y,x,0);
}
void init(){
    n=read();S=0,T=n+1;cnt=n+1;
    for(int i=1;i<=n;++i){
        int x=read();ins(S,i,x);sum+=x;
    }
    for(int i=1;i<=n;++i){
        int x=read();ins(i,T,x);sum+=x;
    }
    m=read();
    for(int i=1;i<=m;++i){
        int k=read(),x=read(),y=read();
        ++cnt;ins(S,cnt,x);ins(cnt+1,T,y);sum+=x+y;
        for(int j=1;j<=k;++j){
            int z=read();ins(cnt,z,inf);ins(z,cnt+1,inf);
        }
        ++cnt;
    }
}
int F(int i){
    return G[i].cap-G[i].flow;
}
bool bfs(){
    queue<int>Q;Q.push(S);
    memset(vis,0,sizeof(vis));vis[S]=1;
    while(!Q.empty()){
        int u=Q.front();Q.pop();
        for(int i=h[u];i;i=G[i].next){
            int v=G[i].to;
            if(vis[v]||F(i)<=0)continue;
            vis[v]=vis[u]+1;
            Q.push(v);
            if(v==T)return 1;
        }
    }return 0;
}
int dfs(int u,int w){
    if(u==T||w==0)return w;
    int flow=0;
    for(int i=h[u];i;i=G[i].next){
        int v=G[i].to;
        if(vis[v]!=vis[u]+1||F(i)<=0)continue;
        if(int t=dfs(v,min(w,F(i)))){
            G[i].flow+=t;G[i^1].flow-=t;
            flow+=t;w-=t;
            if(!w)break;
        }
    }
    if(!flow)vis[u]=0;
    return flow;
}
void dinic(){
    int f=0;
    while(bfs()){
        f+=dfs(S,inf);
    }cout<<sum-f<<endl;
}
int main(){
    init();
    dinic();
    return 0;
}
View Code

 

posted @ 2016-04-08 15:21  117208  阅读(215)  评论(0编辑  收藏  举报