题目链接: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;
}