最大流ISAP算法(邻接表)模板
2010-05-29 21:47
323 查看
const int maxn=201;
const int maxm=201;
struct node
{
int x,y,f,op,next; //x起点,y终点,f权值,next是以x为起点的上一条边在g中的位置,op是反向边在g中的下标位置
}g[maxm*2];
//first[]存储的是以x为起点的最后一条边的在数组g中的下标
//sumd[]用于记录表示标号为i的顶点数有多少个,用于间隙优化
int first[maxn],now[maxn],sumd[maxn];
int ncount; //代表结点的总数
int dis[maxn],fanhui[maxn],pre[maxn],tot; //dis[]用于记录距离标号,pre[i]记录i的前驱在g[]中的位置,tot记录边的总数
void add(int x,int y,int c)
{
tot++; //tot记录边的总数
g[tot].x=x;
g[tot].y=y;
g[tot].f=c;
g[tot].op=tot+1; //反向边在g中的下标位置
g[tot].next=first[x]; //记录以x为起点的上一条边在g中的下标位置
first[x]=tot; //以x为起点的边的位置
tot++;
//反向边
g[tot].x=y;
g[tot].y=x;
g[tot].f=0; //反向边的初始网络流为0
g[tot].op=tot-1;
g[tot].next=first[y];
first[y]=tot;
}
//ISAP算法
int maxflow(int src,int des)
{
int i,flow,t,j,tempmin; //i,j用于标识结点,t用于标识结点在g中的位置
bool flag; //用于标识是否找到了允许路径
int sumFlow;
memset(dis,0,sizeof(dis));
memset(sumd,0,sizeof(sumd));
for(i=1;i<=ncount;i++) //遍历所有的结点
now[i]=first[i];
sumd[0]=ncount; //标号为0的结点有ncount个
sumFlow=0; //sumFlow记录最大流,初始化为0
i=src; //i初始化为起点
flow=10000000;
while(dis[src]<ncount)
{
fanhui[i]=flow;
flag=false;
t=now[i];
while(t!=0) //寻找允许路径
{
j=g[t].y;
if((g[t].f>0)&&(dis[j]+1==dis[i])) //允许弧
{
flag=true;
pre[j]=t;
now[i]=t;
if(g[t].f<flow) //找到允许增量
flow=g[t].f;
i=j;
if(i==des) //找到了允许路径
{
sumFlow+=flow;
while(i!=src) //修改残余网络
{
g[pre[i]].f-=flow; //正向边
g[g[pre[i]].op].f+=flow; //反向边
i=g[pre[i]].x;
}
flow=10000000;
}
break;
}
t=g[t].next;
}
if(flag)
continue;
//没有找到允许路径
tempmin=ncount-1;
t=first[i];
while(t!=0)
{
if((g[t].f>0)&&(dis[g[t].y]<tempmin))
{
tempmin=dis[g[t].y];
now[i]=t;
}
t=g[t].next;
}
sumd[dis[i]]--;
if(sumd[dis[i]]==0) break; //间隙优化
dis[i]=tempmin+1; //此处别忘+1,因为d[i]=tempmin{d[j]+1|(i,j)在残留网络中}
sumd[dis[i]]++;
if(i!=src)
{
i=g[pre[i]].x;
flow=fanhui[i];
}
}
return sumFlow;
}
int main()
{
int src,des; //src是起点,des是终点
memset(first,0,sizeof(first)); //初始化first
tot = 0; //tot初始化为0
ncount = n; //初始化ncount为结点总数
for(i=0;i<N;++i)
{
cin>>x>>y>>c;
add(x,y,c);
}
printf("%d\n",maxflow(src,des));
return 0;
}
const int maxm=201;
struct node
{
int x,y,f,op,next; //x起点,y终点,f权值,next是以x为起点的上一条边在g中的位置,op是反向边在g中的下标位置
}g[maxm*2];
//first[]存储的是以x为起点的最后一条边的在数组g中的下标
//sumd[]用于记录表示标号为i的顶点数有多少个,用于间隙优化
int first[maxn],now[maxn],sumd[maxn];
int ncount; //代表结点的总数
int dis[maxn],fanhui[maxn],pre[maxn],tot; //dis[]用于记录距离标号,pre[i]记录i的前驱在g[]中的位置,tot记录边的总数
void add(int x,int y,int c)
{
tot++; //tot记录边的总数
g[tot].x=x;
g[tot].y=y;
g[tot].f=c;
g[tot].op=tot+1; //反向边在g中的下标位置
g[tot].next=first[x]; //记录以x为起点的上一条边在g中的下标位置
first[x]=tot; //以x为起点的边的位置
tot++;
//反向边
g[tot].x=y;
g[tot].y=x;
g[tot].f=0; //反向边的初始网络流为0
g[tot].op=tot-1;
g[tot].next=first[y];
first[y]=tot;
}
//ISAP算法
int maxflow(int src,int des)
{
int i,flow,t,j,tempmin; //i,j用于标识结点,t用于标识结点在g中的位置
bool flag; //用于标识是否找到了允许路径
int sumFlow;
memset(dis,0,sizeof(dis));
memset(sumd,0,sizeof(sumd));
for(i=1;i<=ncount;i++) //遍历所有的结点
now[i]=first[i];
sumd[0]=ncount; //标号为0的结点有ncount个
sumFlow=0; //sumFlow记录最大流,初始化为0
i=src; //i初始化为起点
flow=10000000;
while(dis[src]<ncount)
{
fanhui[i]=flow;
flag=false;
t=now[i];
while(t!=0) //寻找允许路径
{
j=g[t].y;
if((g[t].f>0)&&(dis[j]+1==dis[i])) //允许弧
{
flag=true;
pre[j]=t;
now[i]=t;
if(g[t].f<flow) //找到允许增量
flow=g[t].f;
i=j;
if(i==des) //找到了允许路径
{
sumFlow+=flow;
while(i!=src) //修改残余网络
{
g[pre[i]].f-=flow; //正向边
g[g[pre[i]].op].f+=flow; //反向边
i=g[pre[i]].x;
}
flow=10000000;
}
break;
}
t=g[t].next;
}
if(flag)
continue;
//没有找到允许路径
tempmin=ncount-1;
t=first[i];
while(t!=0)
{
if((g[t].f>0)&&(dis[g[t].y]<tempmin))
{
tempmin=dis[g[t].y];
now[i]=t;
}
t=g[t].next;
}
sumd[dis[i]]--;
if(sumd[dis[i]]==0) break; //间隙优化
dis[i]=tempmin+1; //此处别忘+1,因为d[i]=tempmin{d[j]+1|(i,j)在残留网络中}
sumd[dis[i]]++;
if(i!=src)
{
i=g[pre[i]].x;
flow=fanhui[i];
}
}
return sumFlow;
}
int main()
{
int src,des; //src是起点,des是终点
memset(first,0,sizeof(first)); //初始化first
tot = 0; //tot初始化为0
ncount = n; //初始化ncount为结点总数
for(i=0;i<N;++i)
{
cin>>x>>y>>c;
add(x,y,c);
}
printf("%d\n",maxflow(src,des));
return 0;
}
相关文章推荐
- 网络流模板:最大流ISAP算法和Dinic算法
- 最大流ISAP算法模板
- EK(BFS)求最大流的算法模板(邻接表)
- POJ3281 Dining 最大流 邻接表[模板]
- 网络流模板:最大流ISAP算法和Dinic算法
- 最大流SAP -邻接表模板
- POJ 1469 COURSES(二分图最大匹配) (矩阵和邻接表的模板题)
- hdu1569 方格取数(2) (最大流 E_K)模板 邻接表
- HDU1532 最大流-模板题
- P3386 【模板】二分图匹配(匈牙利&最大流)
- [最小环 最小环计数 最大平均环 模板题] POJ 1734 Sightseeing trip & FZU 2090 旅行社的烦恼 & POJ 2949 Word Rings
- 算法模板——sap网络最大流 1(非递归+邻接矩阵)
- 【匈牙利算法】二分图最大匹配(模板)
- hdu4280 Island Transport (最大流ISAP算法)
- HDU 2063 过山车 【二分图最大匹配(匈牙利模板)】
- HDU 1856 More is better(简单并查集) 【最大并查集人数模板】
- 最大流Sap模板
- ACM网络流模板 最大流ISAP URAL1774
- codeforces 276D Little Girl and Maximum XOR(区间最大异或值--技巧)【模板】
- poj 2117 Electricity 求无向图中去掉一个点后最大的联通分支数 无向图有可能不联通 tarjan求割点模板