网络流小结

来源:互联网 发布:纸张分切软件 编辑:程序博客网 时间:2024/06/05 17:06
第一个问题:
费用流中,原图无负环的前提上,为什么增广时的最短路算法不会陷入负环,即为什么增广后的残图不会出现负环?

其实这是一个很浅显的问题,可是我纠结了好长时间,233。

首先假设残图会出现负环,则其出现负环的原因必然是增广后某些反向弧被加入的残图中。

而增广路肯定是无环的,所以这些反向弧只可能是负环的一部分。

设这些反向弧组成的路径为P,P上各反向弧对应的边组成的路径为P',负环的另一部分组成的路径为Q。

而P成为负环的一部分的前提是P的权值和的绝对值大于Q的权值和。

而上述前提的前提是 P' 的权值和大于Q的权值和。

显然,上述前提与我们要寻找关于权值的最短增广路是相矛盾的。

因为如果上述前提成立,那么我们拿Q来替换P'会得到一条关于权值的更短的增广路。

所以,在原图无负环的前提上,增广后的残图中是不会出现负环的。


ISAP

#include <algorithm>#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#include <queue>#include <cmath>#include <stack>#include <map>#pragma comment(linker, "/STACK:1024000000");#define EPS (1e-8)#define LL long long#define ULL unsigned long long#define _LL __int64#define INF 0x3f3f3f3f#define Mod 6000007using namespace std;const int EDGE = 6000000,POINT = 1010;struct E{    int u,v,Max,next;}edge[EDGE];int head[POINT];int curr[POINT];int Top;void Link(int u,int v,int flow){    edge[Top].u = u;    edge[Top].v = v;    edge[Top].Max = flow;    edge[Top].next = head[u];    head[u] = Top++;}int dis[POINT],gap[POINT],pre[POINT];queue<int> q;void Updata_Dis(int S,int T,int n){    memset(dis,-1,sizeof(dis));    memset(gap,0,sizeof(gap));    dis[T] = 0;    gap[0] = 1;    q.push(T);    int f;    while(q.empty() == false)    {        f = q.front();        q.pop();        for(int p = head[f];p != -1;p = edge[p].next)        {            if(dis[edge[p].v] == -1)            {                dis[edge[p].v] = dis[f] + 1;                gap[dis[f]+1]++;                q.push(edge[p].v);            }        }    }}int ISAP(int S,int T,int n){    memcpy(curr,head,sizeof(curr));    Updata_Dis(S,T,n);    int flow = 0,u = pre[S] = S,p;    while(dis[S] < n)    {        if(u == T)        {            int temp = INF,pos;            for(p = S;p != T;p = edge[curr[p]].v)            {                if(temp > edge[curr[p]].Max)                {                    temp = edge[curr[p]].Max;                    pos = p;                }            }            for(p = S;p != T;p = edge[curr[p]].v)            {                edge[curr[p]].Max -= temp;                edge[curr[p]^1].Max += temp;            }            flow += temp;            u = pos;        }        for(p = curr[u];p != -1;p = edge[p].next)        {            if(dis[edge[p].v]+1 == dis[u] && edge[p].Max)                break;        }        if(p != -1)        {            curr[u] = p;            pre[edge[p].v] = u;            u = edge[p].v;        }        else        {            if((--gap[dis[u]]) == 0)                break;            int temp = n;            for(p = head[u];p != -1;p = edge[p].next)            {                if(temp > dis[edge[p].v] && edge[p].Max)                {                    curr[u] = p;                    temp = dis[edge[p].v];                }            }            dis[u] = temp+1;            gap[dis[u]]++;            u = pre[u];        }    }    //printf("%d\n",flow);    return flow;}int L[410],R[410];int Map[410][410];bool mark[POINT];bool dfs(int s,int pre){    mark[s] = true;    for(int p = head[s] ;p != -1; p = edge[p].next)    {        if(edge[p].v != pre && edge[p].Max)        {            if(mark[edge[p].v] == true || dfs(edge[p].v,s) == false)                return false;        }    }    mark[s] = false;    return true;}bool Judge(int n,int m){    memset(mark,false,sizeof(mark));    for(int i = 1;i <= n; ++i)    {        if(dfs(i+1,-1) == false)        {            return false;        }    }    return true;}int main(){    int i,j,n,m,k;    //freopen("1002.in","r",stdin);    //freopen("data.out","w",stdout);    while(scanf("%d %d %d",&n,&m,&k) != EOF)    {        memset(head,-1,sizeof(head));        Top = 0;        int ans = 0,sum = 0;        int S = 1,T = 1+n+m+1;        for(i = 1;i <= n; ++i)        {            scanf("%d",&L[i]);            ans += L[i];            Link(S,i+1,L[i]);            Link(i+1,S,0);        }        for(i = 1;i <= m; ++i)        {            scanf("%d",&R[i]);            sum += R[i];            Link(n+i+1,T,R[i]);            Link(T,n+i+1,0);        }        for(i = 1;i <= n; ++i)        {            for(j = 1;j <= m; ++j)            {                Link(i+1,1+n+j,k);                Link(1+n+j,i+1,0);            }        }        if(ans != sum || ans > n*m*k || ISAP(S,T,T) != ans)        {            printf("Impossible\n");        }        else if(Judge(n,m) == false)        {            printf("Not Unique\n");        }        else        {            for(i = 0;i < Top; i += 2)            {                if(edge[i].u != S && edge[i].v != T)                {                    Map[edge[i].u - 1][edge[i].v - n-1] = edge[i^1].Max;                }            }            printf("Unique\n");            for(i = 1;i <= n; ++i)            {                for(j = 1;j <= m; ++j)                {                    printf("%d",Map[i][j]);                    if(j == m)                        printf("\n");                    else                        printf(" ");                }            }        }    }    return 0;}


0 0