• 有源汇点有上下界的最小流


    sgu-176

    176. Flow construction

    time limit per test: 0.5 sec.
    memory limit per test: 4096 KB
    input: standard
    output: standard



    You have given the net consisting of nodes and pipes; pipes connect the nodes. Some substance can flow by pipes, and flow speed in any pipe doesn't exceed capacity of this pipe. 
    The substance cannot be accumulated in the nodes. But it is being produced in the first node with the non-negative speed and being consumed with the same speed in the last node. 
    You have some subset taken from the set of pipes of this net. You need to start the motion of substance in the net, and your motion must fully fill the pipes of the given subset. Speed of the producing substance in the first node must be minimal. 
    Calculate this speed and show the scene of substance motion. 
    Remember that substance can't be accumulated in the nodes of the net.

    Input
    Two positive integer numbers N (1<=N<=100) and M have been written in the first line of the input - numbers of nodes and pipes. 
    There are M lines follows: each line contains four integer numbers Ui, Vi, Zi, Ci; the numbers are separated by a space. Ui is the beginning of i-th pipe, Vi is its end, Zi is a capacity of i-th pipe (1<=Zi<=10^5) and Ci is 1 if i-th pipe must be fully filled, and 0 otherwise. 
    Any pair of nodes can be connected only by one pipe. If there is a pipe from node A to node B, then there is no pipe from B to A. Not a single node is connected with itself. 
    There is no pipe which connects nodes number 1 and N. Substance can flow only from the beginning of a pipe to its end.

    Output
    Write one integer number in the first line of the output - it ought to be the minimal speed of the producing substance in the first node. 
    Write M integers in the second line - i-th number ought to be the flow speed in the i-th pipe (numbering of pipes is equal to the input). 
    If it is impossible to fill the given subset, write "Impossible".

    Sample test(s)

    Input
    
    
    Input 1:  
    4 4  
    1 2 2 0  
    2 4 1 1  
    1 3 2 1  
    3 4 3 0  
    Input 2:  
    4 4  
    1 2 1 0  
    2 4 2 1  
    1 3 3 1  
    3 4 2 0
    Output
    
    
    Output 1: 

    1 1 2 2 
    Output 2: 
    Impossible


    题意:有一个管子要运输液体物质,物体的流速不能超过管子的容量,且物质不能再节点有积累,即每个节点的流入量等于流出量,在第一个节点生产的物质的流速与第n个节点的流速一样,求第一个节点的生产速度最小是多少,要是没有满足的情况输出:Impossible;

    给出节点的个数n个管子的个数m,然后m行给出四个数Ui,Vi,Zi,Ci,当Ci=1的时候,要求该段管子的流量为管子容量值,否则是(0,Zi),管子的流向是单向的,1-n没有直接的管子相连;

    若存在最小流量,就输出最小流量,以及每根管子的流量

    分析:

    (1)增加超级源点st和超级汇点sd,对于有上下界的边(i,j)流量(L,R)变为R-L,然后i与sd连接容量是L,st与j连接容量是L;网络中规定不能有流量流入st,也不能有流量流入sd;

    (2)做一次最大流Dinic;

    (3)在汇点sd到st连一条容量是inf的边;

    (4)在做一次最大流Dinic

    (5)当且仅当附加弧都满流是有可行流,最后的最小流是flow[sd->st]^1],st到sd的最大流就是sd到st的最小流;

    程序:

    #include"stdio.h"
    #include"string.h"
    #include"queue"
    #include"stack"
    #define M 222
    #define inf 100000000
    using namespace std;
    struct node
    {
        int u,v,w,c,next;
    }edge[M*M*2];
    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 main()
    {
        int n,m,i;
        while(scanf("%d%d",&n,&m)!=-1)
        {
            init();
            int source=0;
            int sink=n+1;
            int sum=0;
            queue<int>q;//记录输入的边的编号
            while(m--)
            {
                int a,b,c,d;
                scanf("%d%d%d%d",&a,&b,&c,&d);
                if(d==1)
                {
                    add(a,b,c-c,c);
                    q.push(t-2);
                    add(a,sink,c,0);
                    add(source,b,c,0);
                    sum+=c;
                }
                else
                {
                    add(a,b,c,c);
                    q.push(t-2);
                }
            }
            int ans=Dinic(source,sink);//第一次求最大流
            add(n,1,inf,0);
            int ans1=Dinic(source,sink);//第二次求最大流
            if(ans+ans1!=sum)//判断是否是满流
            {
                printf("Impossible
    ");
                continue;
            }
            printf("%d
    ",edge[(t-1)].w);//最小流的值
            int kk=0;
            while(!q.empty())
            {
                if(kk==0)
                    printf("%d",edge[(q.front())].c-edge[(q.front())].w);
                else
                    printf(" %d",edge[(q.front())].c-edge[(q.front())].w);
                q.pop();
                kk++;
            }
            printf("
    ");
        }
    }
    



  • 相关阅读:
    vue-修改vue项目运行端口号
    任正非521央视采访全文
    是施压还是真的决裂?
    贸易战风波继续
    华为对封杀的态度和格局
    美国封锁对华为的影响
    布鲁克斯法则 (Brooks's Law)
    2019第20周日
    如何让自己走的更远
    如何应对中年危机
  • 原文地址:https://www.cnblogs.com/mypsq/p/4348185.html
Copyright © 2020-2023  润新知