zoukankan      html  css  js  c++  java
  • bzoj3438: 小M的作物

    这题是一道最大权闭合图的经典难题(by Rose_max)

    upd:不误人子弟了,这就是一个裸的最小割啊。。。。。

    然后构图的方式就是把作物值分成AB集合,一个在st一边,一个在ed一边,st连作物流量为a[i],作物流ed流量为b[i],对于每一个组合,新建两个点,一个被st流流量为c1,一个流ed流量为c2,然后第一个流去集合中的作物,作物流回第二个点,流量无限。

    sum-最小割

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    int n,sum,st,ed;
    
    struct node
    {
        int x,y,c,next,other;
    }a[2100000];int len,last[110000];
    void ins(int x,int y,int c)
    {
        int k1,k2;
        
        len++;k1=len;
        a[len].x=x;a[len].y=y;a[len].c=c;
        a[len].next=last[x];last[x]=len;
        
        len++;k2=len;
        a[len].x=y;a[len].y=x;a[len].c=0;
        a[len].next=last[y];last[y]=len;
        
        a[k1].other=k2;
        a[k2].other=k1;
    }
    void composition()
    {
        int x;sum=0;
        st=4001,ed=4002;
        len=0;memset(last,0,sizeof(last));
        
        for(int i=1;i<=n;i++)
            scanf("%d",&x), ins(st,i,x), sum+=x;
        for(int i=1;i<=n;i++)
            scanf("%d",&x), ins(i,ed,x), sum+=x;
        int m,c1,c2;
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            int t;
            int chst=n+i,ched=n*2+i;
            scanf("%d%d%d",&t,&c1,&c2);
            ins(st,chst,c1);sum+=c1;
            ins(ched,ed,c2);sum+=c2;
            for(int j=1;j<=t;j++)
                scanf("%d",&x), ins(chst,x,999999999), ins(x,ched,999999999);
        }
    }
    
    //------composition--------
    
    int h[110000],list[110000];
    bool bt_h()
    {
        memset(h,0,sizeof(h));h[st]=1;
        list[1]=st;int head=1,tail=2;
        while(head!=tail)
        {
            int x=list[head];
            for(int k=last[x];k;k=a[k].next)
            {
                int y=a[k].y;
                if(a[k].c>0&&h[y]==0)
                {
                    h[y]=h[x]+1;
                    list[tail]=y;
                    tail++;
                }
            }
            head++;
        }
        if(h[ed]>0)return true;
        return false;
    }
    int findflow(int x,int f)
    {
        if(x==ed)return f;
        int s=0;
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(a[k].c>0&&h[y]==(h[x]+1)&&s<f)
            {
                int t=findflow(y,min(a[k].c,f-s));
                s+=t;a[k].c-=t;a[a[k].other].c+=t;
            }
        }
        if(s==0)h[x]=0;
        return s;
    }
    
    //---------网络流---------- 
    
    int main()
    {
        scanf("%d",&n);
        composition();
        int ans=0;
        while(bt_h()==true)
        {
            ans+=findflow(st,999999999);
        }
        printf("%d
    ",sum-ans);
        return 0;
    }
  • 相关阅读:
    241. Different Ways to Add Parentheses java solutions
    89. Gray Code java solutions
    367. Valid Perfect Square java solutions
    46. Permutations java solutions
    116. Populating Next Right Pointers in Each Node java solutions
    153. Find Minimum in Rotated Sorted Array java solutions
    判断两颗树是否相同
    求二叉树叶子节点的个数
    求二叉树第k层的结点个数
    将二叉排序树转换成排序的双向链表
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/8343539.html
Copyright © 2011-2022 走看看