Codeforces 362 E Petya and Pipes【费用流】好题

来源:互联网 发布:淘宝网店货源哪里找 编辑:程序博客网 时间:2024/06/10 02:03

E. Petya and Pipes
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

A little boy Petya dreams of growing up and becoming the Head Berland Plumber. He is thinking of the problems he will have to solve in the future. Unfortunately, Petya is too inexperienced, so you are about to solve one of such problems for Petya, the one he's the most interested in.

The Berland capital has n water tanks numbered from1 to n. These tanks are connected by unidirectional pipes in some manner. Any pair of water tanks is connected by at most one pipe in each direction. Each pipe has a strictly positive integer width. Width determines the number of liters of water per a unit of time this pipe can transport. The water goes to the city from the main water tank (its number is1). The water must go through some pipe path and get to the sewer tank with cleaning system (its number isn).

Petya wants to increase the width of some subset of pipes by at most k units in total so that the width of each pipe remains integer. Help him determine the maximum amount of water that can be transmitted per a unit of time from the main tank to the sewer tank after such operation is completed.

Input

The first line contains two space-separated integers n andk (2 ≤ n ≤ 50,0 ≤ k ≤ 1000). Then follow n lines, each line contains n integers separated by single spaces. Thei + 1-th row and j-th column contain numbercij — the width of the pipe that goes from tanki to tank j (0 ≤ cij ≤ 106, cii = 0). If cij = 0, then there is no pipe from tanki to tank j.

Output

Print a single integer — the maximum amount of water that can be transmitted from the main tank to the sewer tank per a unit of time.

Examples
Input
5 70 1 0 2 00 0 4 10 00 0 0 0 50 0 0 0 100 0 0 0 0
Output
10
Input
5 100 1 0 0 00 0 2 0 00 0 0 3 00 0 0 0 4100 0 0 0 0
Output
5
Note

In the first test Petya can increase width of the pipe that goes from the 1st to the 2nd water tank by 7 units.

In the second test Petya can increase width of the pipe that goes from the 1st to the 2nd water tank by 4 units, from the 2nd to the 3rd water tank by 3 units, from the 3rd to the 4th water tank by 2 units and from the 4th to 5th water tank by 1 unit.


题目大意:

给你n个点,并且给你这n个点的网络邻接矩阵,你可以对任意边进行增加流量的操作,但是最多不能超过k,问最大流。


思路:


1、我们首先将原图建到网络中:

设定1为源点,设定n为汇点,将各个边都加入网络中,设定其花费为0,流量为其本身流量。


2、那么我们对将原图建立到网络中跑连续增广路算法求费用流的话,此时费用一定为0,最大流量一定是其原图的最大流,那么剩下可以增加进去的流也可以通过同理来求。


3、那么接下来我们将原图中的每条边再引申出来一条边,设定其花费为1,流量为K,首先保证对应一条边的流量不能增加超过K。然后我们再对这样建图的网络跑费用流,其最大流一定可以包含了原图的最大流,所以这里不必担心原图的最大流会不会加进来的问题。接下来判断什么时候终止,显然,我们在跑完SPFA之后,得到的最短路径值就是增加一单位流的花费,那么我们如果这个花费达到了K我们就终止连续增广路算法即可。


4、这个时候我们就保证了只增加流量为K的情况下的最大流。注意K==0的时候需要特殊判定一下。


Ac代码:

#include<stdio.h>#include<string.h>#include<queue>#include<iostream>using namespace std;struct node{    int from;    int to;    int w;    int next;    int num;    int f;}e[1515151];int head[1212];int pre[1212];int path[1212];int dis[1212];int vis[1212];int n,m,cont,ss,tt,k;void add(int from,int to,int f,int w){    e[cont].num=cont;    e[cont].f=f;    e[cont].w=w;    e[cont].to=to;    e[cont].next=head[from];    head[from]=cont++;}int SPFA(){    queue<int >s;    memset(vis,0,sizeof(vis));    for(int i=1;i<=n;i++)dis[i]=0x3f3f3f3f;    dis[ss]=0;    s.push(ss);    while(!s.empty())    {        int u=s.front();        s.pop();        vis[u]=0;        for(int i=head[u];i!=-1;i=e[i].next)        {            int v=e[i].to;            int w=e[i].w;            int f=e[i].f;            if(f&&dis[v]>dis[u]+w)            {                dis[v]=dis[u]+w;                pre[v]=u;                path[v]=e[i].num;                if(vis[v]==0)                {                    vis[v]=1;                    s.push(v);                }            }        }    }    if(dis[tt]==0x3f3f3f3f)return 0;    else return 1;}void MCMF(){    int maxflow=0;    int ans=0;    while(SPFA()==1)    {        int minn=0x3f3f3f3f;        for(int i=tt;i!=ss;i=pre[i])        {            minn=min(minn,e[path[i]].f);        }        for(int i=tt;i!=ss;i=pre[i])        {            e[path[i]].f-=minn;            e[path[i]^1].f+=minn;        }        if(k==0)        {            maxflow+=minn;            continue;        }        if(ans+minn*dis[tt]>k)        {            maxflow+=(k-ans)/dis[tt];            break;        }        ans+=minn*dis[tt];        maxflow+=minn;        if(ans==k)break;    }    printf("%d\n",maxflow);}int main(){    while(~scanf("%d%d",&n,&k))    {        cont=0;        ss=1;        tt=n;        memset(head,-1,sizeof(head));        for(int i=1;i<=n;i++)        {            for(int j=1;j<=n;j++)            {                int tmp;                scanf("%d",&tmp);                if(tmp==0)continue;                else                {                    add(i,j,tmp,0);                    add(j,i,0,0);                    add(i,j,k,1);                    add(j,i,0,-1);                }            }        }        MCMF();    }}





0 0