EK算法: • //网络流EK算法 • #include<iostream> • #include<queue> • using namespace std; • #define INF 0x7fffffff • #define min(a,b) ((a)<(b)?(a):(b)) • int cap[201][201],flow[201][201],a[201]; • //cap[][]表示最大容量,flow[][]表示当前流量 • int s,t,n,m; • void ek() • { • queue<int> q; • int p[201],u,v; • memset(flow,0,sizeof(flow)); • int f=0; • while(1) • { • memset(a,0,sizeof(a)); • memset(p,0,sizeof(p)); • a[s]=INF; • q.push(s); • while(!q.empty()) • { • u=q.front(); • q.pop(); • for(v=1;v<=m;v++) • if(!a[v] && cap[u][v]>flow[u][v]) • { • p[v]=u; • q.push(v); • a[v]=min(a[u],cap[u][v]-flow[u][v]); • } • } • if(a[t]==0) • break; • for(u=t;u!=s;u=p[u]) • { • flow[p[u]][u]+=a[t]; • flow[u][p[u]]-=a[t]; • } • f+=a[t]; • } • printf("%d/n",f); • } • int main() • { • // freopen("in.txt","r",stdin); • while(scanf("%d %d",&n,&m)!=EOF) • { • int i,si,ei,ci; • memset(cap,0,sizeof(cap)); • for(i=0;i<n;i++) • { • scanf("%d %d %d",&si,&ei,&ci); • cap[si][ei]+=ci; • } • s=1; • t=m; • ek(); • } • return 0; • } ISAP算法: //题目类型:纯最大流 //算法实现:ISAP算法(邻接表实现) #include<iostream> #include<cstdio> //#include<conio.h> #include<string.h> using namespace std; 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的顶点数有多少个,用于间隙优化 //now[]临时记录以x为起点的最后一条边在数组g中的下标 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)); //初始化dis为0 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==ncount) //找到了允许路径 { 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() { //freopen("1.txt","r",stdin); int i,j; int N,M; int x,y,c; int src,des; //src是起点,des是终点 while(scanf("%d%d",&N,&M)!=-1) { memset(first,0,sizeof(first)); //初始化first src = 1; des = M; ncount = M; tot = 0; //tot初始化为0 for(i=0;i<N;++i) { cin>>x>>y>>c; add(x,y,c); } printf("%d/n",maxflow(src,des)); } //getch(); return 0; }