昨天学的最高标号预流推进
没看别人代码敲的,后来有一个BUG,参考了一下别人的代码:http://www.cnblogs.com/Open_Source/archive/2010/08/03/1904898.html
能参考的资料太少了,基本上是连蒙带猜写的代码,还好之前学过SAP,网络流的算法原理好像都是基于最大流最小割定理的,组合数学上都有详细的证明!
参考:
1.刘汝佳《算法艺术与信息学竞赛》P321
2.http://trp.jlu.edu.cn/software/net/lssx/4/4.41.htm
总体感觉就像打乒乓球:推过去又送回来!
代码:(注意越界!)
#include<cstdio>
#include<iostream>
using namespace std;
// freopen("data.in","r",stdin);
#include<queue>
#include<cstring>
#define N 105
#define M (N*N+210)*2//double
#define INF 4000000000
int d[N];
struct cmp
{
bool operator()(const int &u,const int &v)const
{
return d[u]<d[v];
}
};
struct Node
{
int u,v,next;
int c;
};
struct Graph
{
Node E[M];
int first[N];
int _V,_E,src,dest;
__int64 rest[N];
int in[N];
priority_queue<int,vector<int>,cmp> active;
void initial(int n)
{
_V=n+2;_E=0;
src=n,dest=n+1;
memset(first,-1,4*_V);//!!
}
void build(int n,int np,int nc,int m)
{
initial(n);
int i,u,v,c;
for(i=0; i<m; i++)
{
scanf("%*[^(](%d,%d)%d",&u,&v,&c);
if(u==v)continue;
add(u,v,c);
}
for(i=0; i<np; i++)
{
int u,c;
scanf("%*[^(](%d)%d",&u,&c);
add(src,u,c);
}
for(i=0; i<nc; i++)
{
int u,c;
scanf("%*[^(](%d)%d",&u,&c);
add(u,dest,c);
}
}
void add(int u,int v,int c){
E[_E].u=u,E[_E].v=v,E[_E].c=c,E[_E].next=first[u],first[u]=_E,_E++;
E[_E].u=v,E[_E].v=u,E[_E].c=0,E[_E].next=first[v],first[v]=_E,_E++;//
}
void calHeight(){
memset(d,-1,sizeof(d));
d[dest]=0;
int que[N],front,rear;
front=rear=0;
que[rear++]=dest;
while(front!=rear){
int v=que[front++],u;
for(int e=first[v]; e!=-1; e=E[e].next){
u=E[e].v;
if(d[u]==-1){
d[u]=d[v]+1;
que[rear++]=u;
}
}
}
d[src]=_V;//!!
}
void preprocess(){
for(int i=0;i<_V;i++)rest[i]=in[i]=0;
rest[src]=INF;active.push(src);
}
inline void push(int u){
for(int e=first[u]; e!=-1&&rest[u]; e=E[e].next){
int v=E[e].v,c=E[e].c;
if(d[E[e].v]+1==d[u]&&E[e].c){
int aug=rest[u]<c?rest[u]:c;//!!
rest[v]+=aug,rest[u]-=aug,E[e].c-=aug,E[e^1].c+=aug;
if(!in[v]&&v!=dest&&v!=src){
active.push(v);
in[v]=true;
}
}
}
}
inline bool relable(int u){
d[u]=_V-1;
for(int e=first[u]; e!=-1; e=E[e].next)if(E[e].c&&d[u]>d[E[e].v])d[u]=d[E[e].v];
d[u]++;
return d[u]!=_V;
}
__int64 preFlowPush()
{
calHeight();
preprocess();
while(!active.empty()){//!!不记录s,t
int u=active.top();
push(u);//从点u进行推流
if(rest[u]&&relable(u))continue;//可以继续推流
active.pop();in[u]=false;//否则弹出队列
}
return rest[dest];
}
void display(){
for(int i=0; i<_V; i++){
for(int e=first[i]; e!=-1; e=E[e].next){
int u=E[e].u,v=E[e].v,c=E[e].c;
cout<<u<<' '<<v<<' '<<c<<endl;
}
}
}
} net;
int main()
{
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
#endif
int n,np,nc,m;
while(cin>>n)
{
cin>>np>>nc>>m;
net.build(n,np,nc,m);
// net.display();
printf("%I64d\n",net.preFlowPush());
}
return 0;
}