昨天学的最高标号预流推进
没看别人代码敲的,后来有一个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; }