SGU212 Data Transmission(高标号预流推进算法)

题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=212

题意:有一个分层图,每个点有一个层次编号。每条边<u,v>满足u的层次加1等于v的编号。每条边有流量上限。求源点到汇点的最大流。

思路:高标号预流推进算法感觉还跟SAP差不多。基本步骤是这样的:

(1)初始化标号,也就是从会点开始BFS一次;

(2)从某个活动点开始找到一条边将流量向后转移,若找不到转(3);

(3)修改该点的标号,继续找。

最后汇点得到的流量就是最大值。

#include <iostream>

#include <cstdio>

#include <string.h>

#include <algorithm>

#include <cmath>

#include <vector>

#include <queue>

#include <set>

#include <stack>

#include <string>

#include <map>





#define max(x,y) ((x)>(y)?(x):(y))

#define min(x,y) ((x)<(y)?(x):(y))

#define abs(x) ((x)>=0?(x):-(x))

#define i64 long long

#define u32 unsigned int

#define u64 unsigned long long

#define clr(x,y) memset(x,y,sizeof(x))

#define CLR(x) x.clear()

#define ph(x) push(x)

#define pb(x) push_back(x)

#define Len(x) x.length()

#define SZ(x) x.size()

#define PI acos(-1.0)

#define sqr(x) ((x)*(x))

#define MP(x,y) make_pair(x,y)



#define FOR0(i,x) for(i=0;i<x;i++)

#define FOR1(i,x) for(i=1;i<=x;i++)

#define FOR(i,a,b) for(i=a;i<=b;i++)

#define DOW0(i,x) for(i=x;i>=0;i--)

#define DOW1(i,x) for(i=x;i>=1;i--)

#define DOW(i,a,b) for(i=a;i>=b;i--)

using namespace std;





void RD(int &x){scanf("%d",&x);}

void RD(i64 &x){scanf("%I64d",&x);}

void RD(u32 &x){scanf("%u",&x);}

void RD(double &x){scanf("%lf",&x);}

void RD(int &x,int &y){scanf("%d%d",&x,&y);}

void RD(i64 &x,i64 &y){scanf("%I64d%I64d",&x,&y);}

void RD(u32 &x,u32 &y){scanf("%u%u",&x,&y);}

void RD(double &x,double &y){scanf("%lf%lf",&x,&y);}

void RD(int &x,int &y,int &z){scanf("%d%d%d",&x,&y,&z);}

void RD(i64 &x,i64 &y,i64 &z){scanf("%I64d%I64d%I64d",&x,&y,&z);}

void RD(u32 &x,u32 &y,u32 &z){scanf("%u%u%u",&x,&y,&z);}

void RD(double &x,double &y,double &z){scanf("%lf%lf%lf",&x,&y,&z);}

void RD(char &x){x=getchar();}

void RD(char *s){scanf("%s",s);}

void RD(string &s){cin>>s;}





void PR(int x) {printf("%d\n",x);}

void PR(i64 x) {printf("%I64d\n",x);}

void PR(u32 x) {printf("%u\n",x);}

void PR(u64 x) {printf("%llu\n",x);}

void PR(double x) {printf("%.4lf\n",x);}

void PR(char x) {printf("%c\n",x);}

void PR(char *x) {printf("%s\n",x);}

void PR(string x) {cout<<x<<endl;}





const int INF=1<<30;

const int N=1505;

const int MAX=300005;



struct node

{

    int u,v,c,flow,next;

};



node edges[MAX<<1];

int h[N],c[N],gap[MAX],head[N],e,s,t;

int n,m,L,visit[N];

priority_queue<pair<int,int> > Q;





void Add(int u,int v,int c)

{

    edges[e].u=u;

    edges[e].v=v;

    edges[e].c=c;

    edges[e].next=head[u];

    head[u]=e++;



    edges[e].u=v;

    edges[e].v=u;

    edges[e].c=0;

    edges[e].next=head[v];

    head[v]=e++;

}



void SPFA()

{

    clr(h,-1);

    queue<int> q;

    int i,u,v;

    q.push(t);

    h[t]=0;visit[t]=1;

    while(!q.empty())

    {

        u=q.front();

        q.pop();

        visit[u]=0;

        for(i=head[u];i!=-1;i=edges[i].next) if(!edges[i].c)

        {

            v=edges[i].v;

            if(h[v]==-1||h[v]>h[u]+1)

            {

                h[v]=h[u]+1;

                if(!visit[v]) visit[v]=1,q.push(v);

            }

        }

    }

}





void init(int x)

{

    clr(gap,0);

    clr(c,0);

    int i;

    FOR0(i,e) edges[i].flow=0;

    SPFA();

    clr(visit,0);

    c[s]=x;

    visit[s]=1;

    Q.push(MP(h[s],s));

    FOR1(i,n) gap[h[i]]++;

}





void push(int i)

{

    int u=edges[i].u,v=edges[i].v;

    int temp=min(edges[i].c-edges[i].flow,c[u]);

    if(temp<=0) return;

    c[u]-=temp;

    c[v]+=temp;

    if(!visit[v]) Q.push(MP(h[v],v)),visit[v]=1;

    edges[i].flow+=temp;

    edges[i^1].flow-=temp;

}



void pushRelable(int u)

{

    visit[u]=0;

    int i,m;

    while(c[u]&&h[u]<2*n+1)

    {

        m=h[u]-1;

        for(i=head[u];i!=-1;i=edges[i].next)

        {

            if(m==h[edges[i].v]&&edges[i].flow<edges[i].c)

            {

                push(i);

                if(!c[u]) break;

            }

        }

        if(!c[u]) break;

        m=INF;

        for(i=head[u];i!=-1;i=edges[i].next)

        {

            if(edges[i].flow<edges[i].c)

            {

                m=min(m,h[edges[i].v]);

            }

        }

        if(m>=2*n+1) break;

        if(m+1==h[u]) continue;

        gap[h[u]]--;

        if(!gap[h[u]])

        {

            FOR1(i,n) if(h[i]>h[u]&&h[i]<2*n+1)

            {

                gap[h[i]]--;

                gap[h[i]=2*n+1]++;

            }

        }

        gap[h[u]=m+1]++;

    }

}





void Maxflow()

{

    init(INF);

    pair<int,int> now;

    while(!Q.empty())

    {

        now=Q.top();

        Q.pop();

        if(now.second!=t) pushRelable(now.second);

    }

}



int main()

{

    RD(n,m,L);

    int i,u,v,c;

    clr(head,-1);

    FOR1(i,n)

    {

        RD(c);

        if(c==1) s=i;

        if(c==L) t=i;

    }

    FOR1(i,m)

    {

        RD(u,v,c);

        Add(u,v,c);

    }

    Maxflow();

    FOR1(i,m) PR(edges[i*2-2].flow);

    return 0;

}

  

你可能感兴趣的:(Data)