POJ 1273(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;

}



你可能感兴趣的:(poj)