1. 程式人生 > >網絡流小結

網絡流小結

n-1 uniq stdout 問題 %d 出現 mat 但是 comment

第一個問題:
費用流中。原圖無負環的前提上。為什麽增廣時的最短路算法不會陷入負環。即為什麽增廣後的殘圖不會出現負環?

事實上這是一個非常淺顯的問題。但是我糾結了好長時間。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 6000007

using 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;
}


網絡流小結