• 有源汇有上下界的最大流


    ZOJ--3229

    Shoot the Bullet
    Time Limit: 2 Seconds Memory Limit: 32768 KB Special Judge
    Gensokyo is a world which exists quietly beside ours, separated by a mystical border. It is a utopia where humans and other beings such as fairies,youkai(phantoms), and gods live peacefully together. Shameimaru Aya is a crow tengu with the ability to manipulate wind who has been inGensokyo for over 1000 years. She runs the Bunbunmaru News - a newspaper chock-full of rumors, and owns theBunkachou - her record of interesting observations for Bunbunmaru News articles and pictures of beautifuldanmaku(barrange) or cute girls living in Gensokyo. She is the biggest connoisseur of rumors about the girls ofGensokyo among the tengu. Her intelligence gathering abilities are the best inGensokyo!
    During the coming n days, Aya is planning to take many photos of m cute girls living in Gensokyo to write Bunbunmaru News daily and record at leastGx photos of girl x in total in the Bunkachou. At thek-th day, there are Ck targets, Tk1,Tk2, ..., TkCk. The number of photos of targetTki that Aya takes should be in range [Lki,Rki], if less, Aya cannot write an interesting article, if more, the girl will become angry and use herlast spell card to attack Aya. What's more, Aya cannot take more than Dk photos at the k-th day. Under these constraints, the more photos, the better.
    Aya is not good at solving this complex problem. So she comes to you, an earthling, for help.
    Input
    There are about 40 cases. Process to the end of file.
    Each case begins with two integers 1 <= n <= 365, 1 <= m <= 1000. Thenm integers, G1, G2, ..., Gm in range [0, 10000]. Thenn days. Each day begins with two integer 1 <= C <= 100, 0 <= D <= 30000. Then C different targets. Each target is described by three integers, 0 <=T < m, 0 <= L <= R <= 100.
    Output
    For each case, first output the number of photos Aya can take, -1 if it's impossible to satisfy her needing. If there is a best strategy, output the number of photos of each girl Aya should take at each day on separate lines. The output must be in the same order as the input. If there are more than one best strategy, any one will be OK.
    Output a blank line after each case.
    Sample Input
    2 3
    12 12 12
    3 18
    0 3 9
    1 3 9
    2 3 9
    3 18
    0 3 9
    1 3 9
    2 3 9

    2 3
    12 12 12
    3 18
    0 3 9
    1 3 9
    2 3 9
    3 18
    0 0 3
    1 3 6
    2 6 9

    2 3
    12 12 12
    3 15
    0 3 9
    1 3 9
    2 3 9
    3 21
    0 0 3
    1 3 6
    2 6 12

    Sample Output
    36
    6
    6
    6
    6
    6
    6

    36
    9
    6
    3
    3
    6
    9

    -1



    题目大意:一个屌丝给m个女神拍照,计划拍照n天,每一天屌丝最多个C个女神拍照,每天拍照数不能超过D张,而且给每个女神i拍照有数量限制[Li,Ri],对于每个女神n天的拍照总和不能超过Gi,如果有解求屌丝最多能拍多少张照,并求每天给对应女神拍多少张照;否则输出-1。
    解题思路:增设一源点st,汇点sd,st到第i天连一条上界为Di下界为0的边,每个女神到汇点连一条下界为Gi上界为oo的边,对于每一天,当天到第i个女孩连一条[Li,Ri]的边。
    建图模型:源点s,终点d。超级源点ss,超级终点dd。首先判断是否存在满足所有边上下界的可行流,方法可以转化成无源汇有上下界的可行流问题。怎么转换呢?
    增设一条从d到s没有下界容量为无穷的边,那么原图就变成了一个无源汇的循环流图。接下来的事情一样,超级源点ss连i(du[i]>0),i连超级汇点(du[i]<0),
    对(ss,dd)进行一次最大流,当maxflow等于所有(du[]>0)之和时,有可行流,否则没有。
    当有可行流时,删除超级源点ss和超级终点dd,再对(s,d)进行一次最大流,此时得到的maxflow则为题目的解。为什么呢?因为第一次maxflow()只是求得所有满足下界的流量,而残留网络(s,d)路上还有许多自由流(没有和超级源点和超级汇点连接的边)没有流满,所有最终得到的maxflow=(第一次流满下界的流+第二次能流通的自由流)。

    #include"stdio.h"
    #include"string.h"
    #include"queue"
    #include"stack"
    #define M 1500
    #define inf 100000000
    using namespace std;
    struct node
    {
        int u,v,w,c,next;
    }edge[900000];
    int t,head[M],work[M],dis[M];
    void init()
    {
        t=0;
        memset(head,-1,sizeof(head));
    }
    void add(int u,int v,int w,int c)
    {
        edge[t].u=u;
        edge[t].v=v;
        edge[t].w=w;
        edge[t].c=c;
        edge[t].next=head[u];
        head[u]=t++;
    
        edge[t].u=v;
        edge[t].v=u;
        edge[t].w=0;
        edge[t].c=c;
        edge[t].next=head[v];
        head[v]=t++;
    }
    int bfs(int source,int sink)
    {
        memset(dis,-1,sizeof(dis));
        queue<int>q;
        q.push(source);
        dis[source]=0;
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int i=head[u];i!=-1;i=edge[i].next)
            {
                int v=edge[i].v;
                if(edge[i].w&&dis[v]==-1)
                {
                    dis[v]=dis[u]+1;
                    q.push(v);
                    if(v==sink)
                        return 1;
                }
            }
        }
        return 0;
    }
    int dfs(int cur,int a,int sink)
    {
        if(cur==sink)return a;
        for(int &i=work[cur];i!=-1;i=edge[i].next)
        {
            int v=edge[i].v;
            if(edge[i].w&&dis[v]==dis[cur]+1)
            {
                int tt=dfs(v,min(a,edge[i].w),sink);
                if(tt)
                {
                    edge[i].w-=tt;
                    edge[i^1].w+=tt;
                    return tt;
                }
            }
        }
        return 0;
    }
    int Dinic(int start,int sink)
    {
        int ans=0;
        while(bfs(start,sink))
        {
            memcpy(work,head,sizeof(head));
            while(int tt=dfs(start,inf,sink))
                ans+=tt;
        }
        return ans;
    }
    int D[444],G[1111],g[1111];
    int main()
    {
        int n,m,i,j;
        while(scanf("%d%d",&n,&m)!=-1)
        {
            int Di,Ci;
            init();
            int source=0;//虚拟源点
            int sink=m+n+1;//虚拟汇点
            int S=m+n+2;//超级源点
            int T=m+n+3;//超级汇点
            int gsum=0;
            int sum=0;
            memset(G,0,sizeof(G));
            memset(D,0,sizeof(D));
            for(i=1;i<=m;i++)
            {
                scanf("%d",&g[i]);
                gsum+=g[i];
                sum+=g[i];
                add(i+n,sink,inf-g[i],0);//每个女孩与sink连接
            }
            add(S,sink,gsum,0);//超级源点和虚拟汇点连接
            for(i=1;i<=n;i++)
            {
                scanf("%d%d",&Ci,&Di);
                for(j=1;j<=Ci;j++)
                {
                    int a,b,c;
                    scanf("%d%d%d",&a,&b,&c);
                    a++;
                    add(i,a+n,c-b,c);//第i天和第j个女孩连接
                    D[i]+=b;
                    G[a]+=b;
                }
                add(source,i,Di,0);//源点source和第i天连接
            }
            int tt=t;
            for(i=1;i<=n;i++)
            {
                add(i,T,D[i],0);//第i天和超级汇点T连接
                sum+=D[i];
            }
            for(i=1;i<=m;i++)
            {
                add(S,i+n,G[i],0);//超级源点和第j个女孩连接
                add(i+n,T,g[i],0);//第j个女孩和超级汇点连接
            }
    
            add(sink,source,inf,0);//
            int ans=Dinic(S,T);
            //printf("%d %d
    ",ans,sum);
            if(ans!=sum)
                printf("-1
    ");
            else
            {
                t=tt;
                int SS=Dinic(source,sink);
                printf("%d
    ",SS);
                for(int u=1;u<=n;u++)
                {
                    stack<int>p;
                    for(i=head[u];i!=-1;i=edge[i].next)
                    {
                        int v=edge[i].v;
                        if(v>=n+1&&v<=m+n)
                        {
                            //printf("%d--%d
    ",u,v);
                            p.push(edge[i].c-edge[i].w);//因为按照输入的顺序输出答案,而该建图方式的遍历和输入顺序刚好相反
                            SS+=edge[i].c-edge[i].w;//所以先把答案压入栈中
                        }
                    }
                    while(!p.empty())
                    {
                        printf("%d
    ",p.top());//然后从栈中调取答案
                        p.pop();
                    }
                }
            }
            printf("
    ");
        }
        return 0;
    }
    





  • 相关阅读:
    这是阿里技术专家对 SRE 和稳定性保障的理解
    阿里四年技术 TL 的得失总结:如何做好技术 Team Leader
    深度 | 阿里云蒋江伟:什么是真正的云原生?
    亲历者说 | 完整记录一年多考拉海购的云原生之路
    Seata RPC 模块的重构之路
    对容器镜像的思考和讨论
    20 行代码:Serverless 架构下用 Python 轻松搞定图像分类和预测
    怎么提升写代码的能力
    云原生 DevOps 的 5 步升级路径
    dubbo-go 白话文 | 从零搭建 dubbogo 和 dubbo 的简单用例
  • 原文地址:https://www.cnblogs.com/mypsq/p/4348186.html
Copyright © 2020-2023  润新知