• bzoj4485: [Jsoi2015]圈地


    思维僵化选手在线被虐

    其实应该是不难的,题目明显分成两个集合,要求是不同集合的点不能联通

    先假设全选了,然后二分图最小割,相邻两个点直接连墙的费用就可以了

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    
    #define pt(x,y) ((x-1)*m+y)
    using namespace std;
    const int _=1e2;
    const int maxp=400*400+_;
    
    struct node
    {
        int x,y,c,next;
    }a[10*maxp];int len,last[maxp];
    void ins(int x,int y,int c)
    {
        len++;
        a[len].x=x;a[len].y=y;a[len].c=c;
        a[len].next=last[x];last[x]=len;
        
        len++;
        a[len].x=y;a[len].y=x;a[len].c=c;
        a[len].next=last[y];last[y]=len;
    }
    int h[maxp],st,ed;
    int list[maxp];
    bool bt_h()
    {
        memset(h,0,sizeof(h));h[st]=1;
        int head=1,tail=2;list[1]=st;
        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;
                }
            }
            head++;
        }
        return h[ed]!=0;
    }
    int cur[maxp];
    int findflow(int x,int f)
    {
        if(x==ed)return f;
        int s=0;
        for(int k=cur[x];k;k=a[k].next)
        {
            cur[x]=k;
            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[k^1].c+=t;
                if(s==f)break;
            }
        }
        if(s==0)h[x]=0;
        return s;
    }
    
    //-------------------------findflow-----------------------------------
    
    int main()
    {
        int n,m,x,ans=0;
        scanf("%d%d",&n,&m); len=1; st=n*m+1,ed=n*m+2;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                scanf("%d",&x); ans+=abs(x);
                if(x>0)ins(st,pt(i,j),x);
                else if(x<0)ins(pt(i,j),ed,-x);
            }
        for(int i=2;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                scanf("%d",&x);
                ins(pt(i-1,j),pt(i,j),x);
            }
        for(int i=1;i<=n;i++)
            for(int j=2;j<=m;j++)
            {
                scanf("%d",&x);
                ins(pt(i,j-1),pt(i,j),x);
            }
            
        while(bt_h())
        {
            for(int i=1;i<=n*m+2;i++)cur[i]=last[i];
            ans-=findflow(st,(1<<30));
        }
        printf("%d
    ",ans);
        
        return 0;
    }
  • 相关阅读:
    LeetCode Flatten Binary Tree to Linked List
    LeetCode Longest Common Prefix
    LeetCode Trapping Rain Water
    LeetCode Add Binary
    LeetCode Subsets
    LeetCode Palindrome Number
    LeetCode Count and Say
    LeetCode Valid Parentheses
    LeetCode Length of Last Word
    LeetCode Minimum Depth of Binary Tree
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/10615451.html
Copyright © 2020-2023  润新知