【整合】网络流ISAP算法模板

注释应该比较清楚了吧= =
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 2048
#define MAXINT 0x7fffffff
using namespace std;
int n,m;//点的数目和边的数目
int dis[MAXN+1];//距离标号
int num[MAXN+1];
int src,des;//src源点,des汇点
int u,v,w;
struct edge
{
	int f;//某条弧当前流量
	int c;//容量
	int ver;//弧的起点
	edge *rev;//反弧
	edge *next;//弧的终点
	edge(){};
	edge(int v,int cap,edge *nex):ver(v),c(cap),next(nex),rev(NULL),f(0){};
	void* operator new(size_t, void *p)
	{
 		return p;
 	}
}*s[MAXN+1];
void init()
{
	int queue[MAXN+1],head=0,tail=0;
	for (int i=1;i<=n;i++)
	    dis[i]=MAXN,num[i]=0;
	queue[tail++]=des;
	dis[des]=0;
	num[0]=1;
	while (head!=tail)
	{
		int v=queue[head++];
		edge *e=s[v];
		while (e)
		{
			if ((e->rev)&&(e->rev->c==0)||dis[e->ver]<MAXN) {}//若改点后的边不可通过
			//流或者已经更新就无需更新
			else
			{
				dis[e->ver]=dis[v]+1;
				++num[dis[e->ver]];
				queue[tail++]=e->ver;
			}
			e=e->next;
		}
	}
}
int maxflow()//ISAP算法实现过程
{
	int st=src,ret=0;
	edge *E[MAXN],*rep[MAXN];
	for (int i=1;i<=n;i++) E[i]=s[i];
	while (dis[src]<n)//不存在增广路径就停止
	{
		if (st==des)//找到了增广路径
		{
			int delta=MAXINT;
			for (int i=src;i!=des;i=E[i]->ver)
				delta=min(delta,E[i]->c);
			for (int i=src;i!=des;i=E[i]->ver)
			{
				E[i]->c-=delta;
				E[i]->f+=delta;
				E[i]->rev->c+=delta;
				E[i]->rev->f-=delta;
			}
			ret+=delta;
			st=src;
		}
		edge *e;
		for (e=E[st];e;e=e->next)
			if (e->c>0&&dis[st]==dis[e->ver]+1) break;
		if (e)//存在允许弧
		{
			E[st]=e;
			rep[e->ver]=e->rev;
			st=e->ver;
		}
		else
		{
			if ((--num[dis[st]])==0) break;//GAP优化
			E[st]=s[st];
			int mind=n;
			for (edge *t=s[st];t;t=t->next)
				if (t->c>0)
				    mind=min(mind,dis[t->ver]);
			dis[st]=mind+1;
			++num[dis[st]];
			if (st!=src) st=rep[st]->ver;
		}
    }
	return ret;
}
int main()
{
	freopen("ditch.in","r",stdin);
	freopen("ditch.out","w",stdout);
	scanf("%d%d",&m,&n);
	src=1,des=n;
	edge *buffer=new edge[2*m];
 	edge *data=buffer;
	while (m--)
	{
		scanf("%d%d%d",&u,&v,&w);
		s[u]=new((void*) data++) edge(v,w,s[u]);
		s[v]=new((void*) data++) edge(u,0,s[v]);
		s[u]->rev=s[v];
		s[v]->rev=s[u];
	}
	init();
	printf("%d",maxflow());
}
时间: 2024-10-09 23:23:17

【整合】网络流ISAP算法模板的相关文章

最大流ISAP算法模板

这两天学习了最大流,下面是ISAP算法模板: const int inf = 0x3fffffff; template <int N, int M> struct Isap { int top; int d[N], pre[N], cur[N], gap[N]; struct Vertex{ int head; } V[N]; struct Edge{ int v, next; int c, f; } E[M]; void init(){ memset(V, -1, sizeof(V)); t

POJ 1273 Drainage Ditches(网络流dinic算法模板)

POJ 1273给出M条边,N个点,求源点1到汇点N的最大流量. 本文主要就是附上dinic的模板,供以后参考. #include <iostream> #include <stdio.h> #include <algorithm> #include <queue> #include <string.h> /* POJ 1273 dinic算法模板 边是有向的,而且存在重边,且这里重边不是取MAX,而是累加和 */ using namespace

图论专题小结:网络流算法之ISAP算法

ISAP算法 ISAP(Improved Shortest Augument Path)算法是改进版的SAP算法,如果对效率要求很高的时候,可以用该算法. (1)概述:算法基于这样的一个事实:每次增广之后,任意结点到汇点(在残余网络中)的最短距离都不会减小.这样,我们可以利用d[i[表示结点i到汇点的距离的下界.然后再增广过程当中不断地修改这个下界.增广的时候和Dinic算法类似,只允许沿着d[i]==d[j]+1的弧(i,j)走. 不难证明,d[i[满足两个条件:(1)d[t]=0;(2)对任

tarjan算法模板

var {left表示点 root 没离开栈 vis表示点 root 有没有被访问过} i,n,m,now,time,color,top:longint; v:array[0..10001] of record start:longint;end; e:array[0..100001] of record y,next:longint;end; dfn,low,stack,encolor:array[0..10001] of longint; vis,left:array[0..10001] o

prim算法模板

var g:array[1..10,1..10] of longint; d:array[1..10] of longint; f:array[1..10] of boolean; procedure prim; var i,j,k,min:longint; begin fillchar(g,sizeof(g),0); fillchar(f,sizeof(f),0); for i:=1 to n do d[i]:=g[1,i]; f[1]:=true; for i:=2 to n do begi

bellman-ford算法模板

有SPFA模板,bellman-ford模板显然是多余的. var e:array[1..maxe]of record a,b,w:longint;end; { 距源点s距离 } dis:array[1..maxn]of longint; { 前驱 } pre:array[1..maxn]of longint; m,n,s:longint; procedure relax(u,v,w:longint); begin if dis[u]+w<dis[v] then begin dis[v]:=di

Floyd判最小环算法模板

算法思想:如果存在最小环,会在编号最大的点u更新最短路径前找到这个环,发现的方法是,更新最短路径前,遍历i,j点对,一定会发现某对i到j的最短路径长度dis[i][j]+mp[j][u]+mp[u][i] != INF,这时i,j是图中挨着u的两个点,因为在之前最短路更新过程中,u没有参与更新,所以dis[i][j]所表示的路径中不会出现u,如果成立,则一定是一个环.用Floyd算法来实现.但是对于负环此算法失效,因为有负环时,dis[i][j]已经不能保证i到j的路径上不会经过同一个点多次了.

hdu 1711 KMP算法模板题

题意:给你两个串,问你第二个串是从第一个串的什么位置開始全然匹配的? kmp裸题,复杂度O(n+m). 当一个字符串以0为起始下标时.next[i]能够描写叙述为"不为自身的最大首尾反复子串长度". 当发生失配的情况下,j的新值next[j]取决于模式串中T[0 ~ j-1]中前缀和后缀相等部分的长度, 而且next[j]恰好等于这个最大长度. 防止超时.注意一些细节.. 另外:尽量少用strlen.变量记录下来使用比較好,用字符数组而不用string //KMP算法模板题 //hdu

HDU 2544 最短路(我的dijkstra算法模板、SPAFA算法模板)

思路:这道题是基础的最短路径算法,可以拿来试一下自己对3种方法的理解 dijkstra主要是从第一个点开始枚举,每次枚举出当当前最小的路径,然后再以那最小的路径点为起点,求出它到其它未标记点的最短距离 bellman-ford 算法则是假设有向网中有n 个顶点.且不存在负权值回路,从顶点v1 和到顶点v2 如果存在最短路径,则此路径最多有n-1 条边.这是因为如果路径上的边数超过了n-1 条时,必然会重复经过一个顶点,形成回路:而如果这个回路的权值总和为非负时,完全可以去掉这个回路,使得v1到v