今天刻意用poj 3469 http://poj.org/problem?id=3469测了下模板,Isap并不像想象中那么快,难道是我写搓了,而且在网络流与线性规划中的最后一题,isap完败给Dinic了,我的Isap啊~~~不知道那些几百毫秒出解的是用什么算法。。。难道是。。。 dinic总体上挺不错的,递归版的Isap基本上与Dinic没差别,而非递归版在某些情况反而不如递归版,于是以后一般用Dinic,是在不行用非递归的isap试试 所以比赛中就带1,3两个模板好了 费用流居然忘加了,今天把它加上了= =,在最后。。。 模板1(Dinic递归版 3438MS): |
#include
using namespace std;
const int mm=1000000;
const int mn=22222;
const int oo=1000000000;
int node,src,dest,edge;
int reach[mm],flow[mm],next[mm];
int head[mn],work[mn],dis[mn],q[mn];
inline int min(int a,int b)
{
return a=0;i=next[i])
if(flow[i]&&dis[v=reach[i]]<0)
{
dis[q[r++]=v]=dis[u]+1;
if(v==dest)return 1;
}
return 0;
}
int Dinic_dfs(int u,int exp)
{
if(u==dest)return exp;
for(int &i=work[u],v,tmp;i>=0;i=next[i])
if(flow[i]&&dis[v=reach[i]]==dis[u]+1&&(tmp=Dinic_dfs(v,min(exp,flow[i])))>0)
{
flow[i]-=tmp;
flow[i^1]+=tmp;
return tmp;
}dis[u]--;
return 0;
}
int Dinic_flow()
{
int i,ret=0,delta;
while(Dinic_bfs())
{
for(i=0;i
#include
using namespace std;
const int mm=2000000;
const int mn=22222;
const int oo=1000000000;
int node,src,dest,edge;
int reach[mm],flow[mm],next[mm];
int head[mn],gap[mn],h[mn];
inline int min(int a,int b)
{
return a=0;i=next[i])
if(flow[i])
{
if(h[v=reach[i]]+1==h[u])
{
tmp=Isap_dfs(v,min(lv,flow[i]));
flow[i]-=tmp;
flow[i^1]+=tmp;
lv-=tmp;
if(h[src]>=node)return exp-lv;
if(lv==0)break;
}
minh=min(minh,h[v]);
}
if(lv==exp)
{
if(--gap[h[u]]==0)h[src]=node;
++gap[h[u]=minh+1];
}
return exp-lv;
}
int Isap_flow()
{
int i,ret=0;
for(i=0;i
模板3(Isap 非递归版 2610MS):
这个模板有bug, 出现在gap优化里,详细看红色注释
#include
using namespace std;
const int mm=2000000;
const int mn=22222;
const int oo=1000000000;
int node,src,dest,edge;
int ver[mm],flow[mm],next[mm];
int head[mn],work[mn],h[mn],q[mn],gap[mn],p[mn];
inline int min(int a,int b)
{
return a//高度初始为0,否则会访问-1的数组,汇点为1
gap[h[q[r++]=dest]=1]=1;
for(l=0; l=0; i=next[i])
if(flow[i^1]&&!h[v=ver[i]])
++gap[h[q[r++]=v]=h[u]+1];
}
int Isap_flow()
{
int i,u,ret=0,tmp,minh;
Isap_Pre();
for(i=0; i=
{
if(u==dest)
{
for(i=src,tmp=oo;i!=dest;i=ver[work[i]])
tmp=min(tmp,flow[work[i]]);
for(i=src;i!=dest;i=ver[work[i]])
flow[work[i]]-=tmp,flow[work[i]^1]+= tmp;
ret+=tmp,u=src;
}
int &e=work[u];
for(;e>=0;e=next[e])
if(flow[e]&&h[u]==h[ver[e]]+1)break;
if(e>=0)p[u=ver[e]]=e^1;
else
{
if(--gap[h[u]]==0)break;
work[u]=head[u],minh=node;
for(i=head[u];i>=0;i=next[i])
if(flow[i])minh=min(minh,h[ver[i]]);
++gap[h[u]=minh+1];//应该是h[u]=max(h[u],minh)+1,否则gap[h[u]]==0时断层并不能结束,因为可能会降低h[u]导致断层恢复
if(u!=src)u=ver[p[u]];
}
}
return ret;
}
int main()
{
int i,j,n,m,a,b;
while(scanf("%d%d",&n,&m)!=-1)
{
prepare(n+2,0,n+1);
for(i=1;i<=n;++i)
{
scanf("%d%d",&a,&b);
addedge(src,i,a,0);
addedge(i,dest,b,0);
}
while(m--)
{
scanf("%d%d%d",&i,&j,&a);
addedge(i,j,a,a);
}
printf("%d\n",Isap_flow());
}
return 0;
}
改正后的ISAP非递归版本,对应csu 1249,谢谢wyb的数据:
#include
#include
using namespace std;
const int mm=20000;
const int mn=222;
const int oo=1000000000;
int node,src,dest,edge;
int ver[mm],flow[mm],next[mm];
int head[mn],work[mn],h[mn],q[mn],gap[mn],p[mn],cur[mn];
void prepare(int _node,int _src,int _dest)
{
node=_node,src=_src,dest=_dest;
for(int i=0; i=0; i=next[i])
if(flow[i^1]&&!h[v=ver[i]])
h[q[r++]=v]=h[u]+1;
for(i=0; i=0;e=next[e])
if(flow[e]&&h[u]==h[ver[e]]+1)break;
if(e>=0)
{
p[++deep]=u=ver[e];//栈记录节点
cur[deep]=min(cur[deep-1],flow[e]);//栈记录最大流量
continue;
}
if(--gap[h[u]]==0)break;
work[u]=head[u],minh=node;
for(i=head[u];i>=0;i=next[i])
if(flow[i])minh=min(minh,h[ver[i]]);
++gap[h[u]=max(h[u],minh)+1];//一定要比本身大否则gap优化会出错
if(deep>0)u=p[--deep];
}
return ret;
}
int main()
{
int i,j,n,m,a;
while(scanf("%d%d",&n,&m)!=-1)
{
prepare(n+1,1,n);
while(m--)
{
scanf("%d%d%d",&i,&j,&a);
addedge(i,j,a);
}
scanf("%d%d",&src,&dest);
printf("%d\n",Isap_flow());
}
return 0;
}
最小费用最大流,当然最大费用直接把边去相反数即可转换为最小费用。。。
题目:http://acm.hit.edu.cn/hoj/problem/view?id=2715
模板:
#include
#include
using namespace std;
const int mm=66666;
const int mn=5555;
const int oo=1e9;
int src,dest,node,edge;
int dx[]={0,0,-1,1};
int dy[]={-1,1,0,0};
int ver[mm],cost[mm],flow[mm],next[mm];
int head[mn],dis[mn],p[mn],q[mn];
int h[55][55];
bool vis[mn]={0};
void prepare(int _node,int _src,int _dest)
{
node=_node,src=_src,dest=_dest;
for(int i=0;i=0;i=next[i])
if(flow[i]&&dis[v=ver[i]]>(tmp=dis[u]+cost[i]))
{
dis[v]=tmp;
p[v]=i^1;
if(vis[v])continue;
vis[q[r++]=v]=1;
if(r==mn)r=0;
}
return p[dest]>-1;
}
int Spfaflow()
{
int i,delta,ret=0;
while(Spfa())
{
for(i=p[dest],delta=oo;i>=0;i=p[ver[i]])
if(flow[i^1]=0;i=p[ver[i]])
flow[i]+=delta,flow[i^1]-=delta;
ret-=delta*dis[dest];
}
return ret;
}
int main()
{
int i,j,x,y,k,n,m,t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
prepare(n*n*2+3,n*n*2+1,n*n*2+2);
for(i=0;in||y<1||y>n||h[x][y]>=h[i][j])continue;
addedge(n*n+i*n-n+j,x*n-n+y,oo,0);
}
for(i=1;i<=n;++i)
for(j=1;j<=n;++j)
if(i==1||j==1||i==n||j==n)
addedge(n*n+n*i-n+j,dest,oo,0);
addedge(src,0,m,0);
printf("%d\n",Spfaflow());
}
return 0;
}