您的位置:首页 > 其它

最大流:SAP+GAP模版

2014-03-20 13:01 197 查看
题目:POJ-1273最大流模板题code1:链式前向星(1)
#include
#include
#include
#define MAXN 205
#define MAXM 410
#define INT_MAX 0x7fffffff
using namespace std;
int n,m;
struct node
{
int c,next,to;
} edge[MAXM];
int cnt,head[MAXN];
void addedge(int from,int to,int c)//这里存的还是一条有向边
{
edge[cnt].to=to;
edge[cnt].c=c;
edge[cnt].next=head[from]; head[from]=cnt++;
edge[cnt].to=from;
edge[cnt].c=0;     edge[cnt].next=head[to];
head[to]=cnt++;
}
int gap[MAXN],h[MAXN],curedges[MAXN],pre[MAXN];
int start,end;
int SAP_GAP()
{
start=1;
end=n;
//gap;  h:距离标号数组;curedges:当前弧数组;pre前驱数组
int cur_flow,flow_ans=0,u,tmp,neck,i;// 初始化最大0
memset(h,0,sizeof(h));
memset(gap,0,sizeof(gap));
memset(pre,-1,sizeof(pre));
for(i=1; i<=n; i++)
curedges[i]=head[i];//初始化当前弧为第一条邻接边
gap[0]=n;
u=start;
while(h[start]<</span>n)
{   if(u==end)
{   cur_flow=INT_MAX;
for(i=start; i!=end; i=edge[curedges[i]].to)
{   if(cur_flow>edge[curedges[i]].c)
{   neck=i;
cur_flow=edge[curedges[i]].c;
}
}       //增广成功,寻找瓶颈边
for(i=start; i!=end; i=edge[curedges[i]].to)
{  tmp=curedges[i];
edge[tmp].c-=cur_flow;
edge[tmp^1].c=cur_flow;
}
flow_ans+=cur_flow;
u=neck;
}
for(i=curedges[u]; i!=-1; i=edge[i].next)
if(edge[i].c&&h[u]==h[edge[i].to]+1)
break;  //寻找可行弧
if(i!=-1)       //找到可行弧
{   curedges[u]=i;
pre[edge[i].to]=u;
u=edge[i].to;
}
else            //未找到可行弧
{   gap[h[u]]--;
if(gap[h[u]]==0)   break;  //GAP优化
curedges[u]=head[u];
for(tmp=n,i=head[u]; i!=-1; i=edge[i].next)
if(edge[i].c)
tmp=min(tmp,h[edge[i].to]);
h[u]=tmp+1;
++gap[h[u]];
if(u!=start) u=pre[u];
}
}
return flow_ans;
}
void init()
{   int from,to,c;
cnt=0;
memset(head,-1,sizeof(head));
for(int i=0; i<</span>m; i++)
{   scanf("%d%d%d",&from,&to,&c);
addedge(from,to,c);
}
}
int main()
{
//freopen("in.txt","r",stdin);
while(~scanf("%d%d",&m,&n))
{  init();
printf("%d\n",SAP_GAP());
}
return 0;
}
code2:链式前向星(2)
#include
#include
#include
#define inf 0x7fffffff
using namespace std;
const int N=205;
const int M=500;//边是双向存的(注意不是无向)要开正常的2倍大
struct Edge{int v,next,w;} edge[M];int head[N],cnt,n,m,s=1;
int pre[N],cur[N],dis[N],gap[N];
void addedge(int u,int v,int w)//这里存的还是一条有向边
{  edge[cnt].v=v;edge[cnt].w=w;
edge[cnt].next=head[u];head[u]=cnt++;
edge[cnt].v=u;edge[cnt].w=0;
edge[cnt].next=head[v];head[v]=cnt++;
}
int sap()
{  int flow=0,aug=inf,u;bool flag;
memset(pre,-1,sizeof(pre));memset(dis,0,sizeof(dis));
memset(gap,0,sizeof(gap));
for(int i=1; i<=n; i++)
cur[i]=head[i];
gap[s]=n;   //初始化时全部处于gap[s]
u=pre[s]=s;
while(dis[s]<</span>n)
{   flag=0;
for(int &j=cur[u]; j!=-1; j=edge[j].next)
{  int v=edge[j].v;
if(edge[j].w>0&&dis[u]==dis[v]+1)
{flag=1;
if(edge[j].w<</span>aug) aug=edge[j].w;
pre[v]=u;u=v;
if(u==n)    //如果到达end
{   flow+=aug;
while(u!=s)
{   u=pre[u];
edge[cur[u]].w-=aug;
edge[cur[u]^1].w+=aug;//异或是找与其配对的边
}
aug=inf;
}
break;
}
}
if(flag)                      //未找到可行边
continue;
int mindis=n;
for(int j=head[u]; j!=-1; j=edge[j].next)
{    int v=edge[j].v;
if(edge[j].w>0&&dis[v]<</span>mindis)
{  mindis=dis[v];cur[u]=j;}
}
if((--gap[dis[u]])==0)break;
dis[u]=mindis+1;
gap[dis[u]]++;
u=pre[u];
}
return flow;
}
void init()
{   int from,to,c;cnt=0;
memset(head,-1,sizeof(head));
for(int i=0;i<</span>m;i++)
{  scanf("%d%d%d",&from,&to,&c);addedge(from,to,c);}
}
int main()
{   while(~scanf("%d%d",&m,&n))
{
init();
printf("%d\n",sap());
}
return 0;
}
code3:邻接矩阵
#include
#include
#include
#define M 205
using namespace std;
const int inf=~0U>>1;
int n,nb,nc,m;
int gap[M],flow[M][M],dist[M],cur[M];int pre[M];int source,end,s,t;
int sap()
{s=source;t=end;
memset(cur,0,sizeof(cur));memset(dist,0,sizeof(dist));  memset(gap,0,sizeof(gap));
int u=pre[s]=s,maxflow=0,aug=inf;
gap[0]=n;
while(dist[s]<</span>n)
{
loop:
for(int v=cur[u];v<=n;v++)
{  if(flow[u][v]&&dist[u]==dist[v]+1)
{
cur[u]=v;aug=min(aug,flow[u][v]);
pre[v]=u;u=v;
if(v==t)
{    maxflow+=aug;
for(u=pre[u];v!=s;v=u,u=pre[u])
flow[u][v]-=aug,flow[v][u]+=aug;
aug=inf;
}
goto loop;
}
}
int mind=n;
for(int v=1;v<=n;v++)
if(flow[u][v]&&(mind>dist[v]))
{cur[u]=v;mind=dist[v];}
if((--gap[dist[u]])==0) break;
gap[dist[u]=mind+1]++;
u=pre[u];
}
return maxflow;
}
void init()
{        int from,to,c;
memset(flow,0,sizeof(flow));//没加这个 wa了4次
for(int i=0;i<</span>m;i++)
{scanf("%d%d%d",&from,&to,&c);flow[from][to]+=c;}
source=1;end=n;
}
int main()
{int x,y,c;
while(~scanf("%d%d",&m,&n))
{
init();
printf("%d\n",sap());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: