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;
}

posted @ 2010-05-29 21:41  北海小龙  阅读(472)  评论(0编辑  收藏  举报