ISAP算法

第一步先用BFS给各个节点标层次。用的是到终点的距离进行标记。

从终点开始从0到终点为起点给各个点进行标记。


第二步从起点出发对给点到终点的路径。

有剩余流量并且相邻的点的距离函数比此点小1的话,探索的点x前进到相邻的点。

有剩余流量但是距离函数不符合的话把此点的距离函数标记成有剩余流量的最小数加1。

并把探索的点置为探索点x的路径上前一个点。(如果x不是起点的话)

x是起点的话则x不变。

当x为终点时把此路径上的流量加入总流量。

当起点的距离函数为结点数时终结探索过程。

当值为某个值距离函数的总数为0点时,此图不再连通。终结过程。

代码为poj1459的ISAP的代码

#include<iostream>  
using namespace std; 

struct Edge
{
    int cap, flow;	
};

Edge edges[200][200];
int size;
int visit[200], s, t;
int p[1000000], num[1000000];
int q[1000000], d[1000000];
int Count;

int BFS()
{
	int i, front, tail,temp;
	for(i = 0; i < size + 2 ; i++)
	{
		visit[i] = 0;
	}
	
	front = 0; tail = 1;
	q[front] = t;
	visit[t] = 1; 
	d[t] = 0;
	num[d[t]]++;
	while(front < tail)
	{
		
		temp = q[front];
		front++;
		for(i = 0; i < size + 2 ; i++)
		{
			if(!visit[i] && edges[i][temp].cap > edges[i][temp].flow)
			{
				q[tail] = i;
				d[i] = d[temp] + 1;
				num[d[i]]++;
				visit[i] = 1;
				tail++;
			}
		}
	}
	
	return visit[t];
}

int augment()
{
	int a = 1000000, temp;
	for(int i = 0; i < Count - 1; i++)
	{
		temp = edges[p[i]][p[i + 1]].cap - edges[p[i]][p[i + 1]].flow;
		if(temp < a)
			a = temp;
	}
	
	for(int i = 0; i < Count - 1; i++)
	{
		edges[p[i]][p[i + 1]].flow += a;
		edges[p[i + 1]][p[i]].flow -= a;
	}
//	for(int i = 0; i < Count ; i++)
//	{
//		cout << "aaa   " << p[i] << " " << a <<endl;
//	}
//	cout <<endl;
	return a;
}

int maxFlow()
{
	BFS();
	int x = s,i, flow = 0, ok, min, m;
	Count = 0; p[Count++] = s;
	while(d[s] < size + 2 )
	{
		if(x == t)
		{
			flow += augment();
			x = s;  Count = 0;
			p[Count++] =s;
		}
		ok = 0;
		for(i = 0; i < size + 2 ; i++)
		{
			if(d[x] == d[i] + 1 && edges[x][i].cap > edges[x][i].flow)
			{
				ok = 1;
				x = i; p[Count++] = i;
			}
		}
		if(ok == 0)
		{
			min = size + 1;
			for(i = 0; i < size + 2 ; i++)
			{
				if(edges[x][i].cap > edges[x][i].flow)
				{
					if(d[i] < min)
					{
						min = d[i];
						m = i;
					}
				}
			}
			if(--num[d[x]] == 0)
				break;
		    d[x] = min + 1; num[d[x]]++;
			//p[Count++] = m;
			//x = m;
			if(x != s)
			{
				x = p[Count - 2];
				Count --;
			}
		}
	}
	return flow;
}

int main()    
{   
    int faSize, haoSize, linkSize, i, j;  
    int start, end, value;  
    char temp[100];  
    while(scanf("%d", &size) != EOF)  
    {  
        s = size; t = size + 1;  
        scanf("%d%d%d", &faSize, &haoSize, &linkSize);  
        for(i = 0; i < size + 2; i++)  
        {  
            visit[i] = 0; d[i] = 0;  
            for(j = 0; j < size + 2; j++)  
            {  
                edges[i][j].cap = 0; edges[i][j].flow = 0;  
            }  
        }  
        //cout << linkSize << endl;  
        while(linkSize--)  
        {  
            scanf("%s",temp);  
            sscanf(temp,"(%d,%d)%d",&start,&end,&value);  
            //scanf("(%d,%d)%d", &start, &end, &value);  
            //cout << start << " " << end << " " << value;  
            edges[start][end].cap = value;  
			
        }  
        while (faSize--)  
        {  
            scanf("%s",temp);  
            sscanf(temp, "(%d)%d",  &end, &value);  
            edges[s][end].cap = value;  
			
        }  
        while (haoSize--)  
        {  
            scanf("%s",temp);  
            sscanf(temp, "(%d)%d",  &start, &value);  
            edges[start][t].cap = value;  
        }  
		
        cout << maxFlow() <<endl;  
		
 
	}  
	
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值