• P1361 小M的作物


    P1361 小M的作物

    二者取其一类型的网络流题

    不同的集合,向对应元素连去不同(收益)容量的边

    对于那些神奇的组合,我们只需要按照以下方式建立两个点

    1. (X)(S)连一条在A时的额外收益
      2.(X) (X^{star})(注意顺序,(X)是其有向边的起点,(X^{star})是其有向边的终点)向其后继节点连(inf)容量的边,保证不会出现在最小割中
      3.(X^{star})(T)连去一条在(B)时的的收益

    然后将所有边((inf)除外)的权值加起来,减去最小割就是答案

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<queue>
    #include<cstring>
    using std::queue;
    using std::min;
    const int maxn=11000;
    int n,m;
    struct node
    {
        int p;
        long long f;
        int nxt;
    };
    int head[maxn<<1],tail=-1;
    int cur[maxn<<1];
    node line[5000000];
    void add(int a,int b,long long c)
    {
        line[++tail].p=b;
        line[tail].f=c;
        line[tail].nxt=head[a];
        head[a]=tail;
    }
    int dis[maxn<<1];
    bool bfs(int s,int t)
    {
        queue<int>q;
        memset(dis,0,sizeof(dis));
        dis[s]=1;
        q.push(s);
        while(!q.empty())
        {
            int pas=q.front();q.pop();
            for(int i=head[pas];i!=-1;i=line[i].nxt)
                if(!dis[line[i].p]&&line[i].f)
                {
                    dis[line[i].p]=dis[pas]+1;
                    q.push(line[i].p);
                }
        }
        return dis[t];
    }
    long long dfs(int now,int aim,long long flow)
    {
        long long res=0,f;
        if(now==aim||!flow)	return flow;
        for(int &i=cur[now];i!=-1;i=line[i].nxt)
            if(dis[line[i].p]==dis[now]+1&&(f=dfs(line[i].p,aim,min(flow,line[i].f))))
            {
                res+=f;
                flow-=f;
                line[i].f-=f;
                line[i^1].f+=f;
                if(!flow) break;
            }
        return res;
    }
    long long dinic(int s,int t)
    {
        long long res=0;
        while(bfs(s,t))
        {
            for(int i=0;i<=n+m*2+1;i++)
                cur[i]=head[i];
            res+=dfs(s,t,0x7fffffff);
        }
        return res;
    }
    int main()
    {
    	memset(head,-1,sizeof(head));
    	scanf("%d",&n);
        int a,b,c,ans=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a);
            ans+=a;
            add(0,i,a);
            add(i,0,0);
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a);
            ans+=a;
            add(i,n+1,a);
            add(n+1,i,0);
        }
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            add(0,i+n+1,b);
            add(i+n+1,0,0);
            add(i+n+m+1,n+1,c);
            add(n+1,i+n+m+1,0);
            ans+=b+c;
            for(int j=1;j<=a;j++)
            {
                scanf("%d",&b);
                add(i+n+1,b,0x7fffffff);
                add(b,i+n+1,0);
                add(b,i+n+m+1,0x7fffffff);
                add(i+n+m+1,b,0);
            }
        }
        printf("%d",ans-dinic(0,n+1));
    }
    
  • 相关阅读:
    枚举类 --单例模式
    模板设计模式
    动态代理
    反射应用--修改属性值
    通过反射绕过泛型
    java反射
    网络编程练习
    TCP编程
    GUI 聊天界面
    UDP传输多线程
  • 原文地址:https://www.cnblogs.com/Lance1ot/p/9387620.html
Copyright © 2020-2023  润新知