网络流算法之一
1. Edmonds-karp 算法
用广度优先搜索来实现对增广路径p的计算,即如果增广入径是残留网络中从(s到t的最短路径,就能改进FORD-FULKERSON的界,
称Ford-Fulkerson方法的这种实现为Edmonds-karp算法,时间复杂度为O(VE^2);
HDU 3549
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <deque>
using namespace std;
int cap[100][100];
int a[100];
int flow[100][100];
int path[1010];
int N,M;
const int inf = 0x7f7f7f7f;
int f;
int Scan()
{
int res = 0 , ch ;
while( !( ( ch = getchar() ) >= '0' && ch <= '9' ) )
{
if( ch == EOF ) return 1 << 30 ;
}
res = ch - '0' ;
while( ( ch = getchar() ) >= '0' && ch <= '9' )
res = res * 10 + ( ch - '0' ) ;
return res ;
}
void BFS( )
{
int i, j, k, t, u, v;
f = 0;
memset(flow, 0, sizeof(flow));
for (; ; )
{
memset(a, 0, sizeof(a));
memset(path, 0, sizeof(path));
deque<int>q;
a[1] = inf;
q.push_back(1);
while (!q.empty( ))
{
t = q.front( );
q.pop_front( );
for (i = 0; i <= N; i++)
if (!a[i] && flow[t][i] < cap[t][i] )
{
path[i] = t;
a[i] = min(a[t], cap[t][i] - flow[t][i]);
q.push_back(i);
}
}
if (a[N] == 0)
break;
for (u = N; u != 1; u = path[u])
{
flow[path[u]][u] += a[N];
flow[u][path[u]] -= a[N];
}
f += a[N];
}
printf("%d\n",f);
}
int main( )
{
int T, l = 0, i, b, c, d;
scanf("%d", &T);
while (T--)
{
l++;
scanf("%d%d", &N, &M);
memset(cap, 0, sizeof(cap));
for (i = 0; i < M; i++) {
//scanf("%d%d%d", &d, &b, &c);
d = Scan();
b = Scan();
c = Scan();
cap[d][b] += c;
}
printf("Case %d: ",l);
BFS( );
}
return 0;
}
2.压入与重标记算法
算法导论说,目前最快速的实现都是基于压入与重标记方法的。
运用该方法的算法分为好几种:
1.一般的预流推进算法
在残余网络中,维护一个预流,不断对活跃点进行push或release操作来重新调整
整个预留,直到不能操作。时间复杂度O(V*E*E)。
2.先进先出队列预留推进算法
在残余网路中,以先进先出对列维护活跃点,时间复杂度为O(V*V*V);
3.最高标号预留推进算法(HLPP)
在残余网络中,每次检查最高标号的活跃点,需要用到优先队列,
时间复杂度O(V*V*E^0.5)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <deque>
using namespace std;
deque<int>q;
int cap[16][16]; //存储网络容量C,原来数组开了1000,TLE了N久
int flow[16][16]; //存储流过容量f
int e[16]; //每个顶点余流
int h[16]; //每个定点高度
int visit[16]; //标记顶点
int N,vertix;
int Scan()
{
int res = 0 , ch ;
while( !( ( ch = getchar() ) >= '0' && ch <= '9' ) )
{
if( ch == EOF ) return 1 << 30 ;
}
res = ch - '0' ;
while( ( ch = getchar() ) >= '0' && ch <= '9' )
res = res * 10 + ( ch - '0' ) ;
return res ;
}
const int inf = 0x7f7f7f7f;
int min( int x, int y)
{
return x < y ? x : y;
}
void Push( int u, int v)
{
int x = cap[u][v] - flow[u][v];
if( h[u] == h[v] + 1 && e[u] > 0 && x > 0 )
{
x = min(e[u], x);
flow[u][v] += x;
flow[v][u] = -flow[u][v];
e[u] -= x;
e[v] += x;
if( !visit[v] && v != 1 && v != vertix )
{
q.push_back( v );
visit[v] = 1;
}
}
}
void Relable(int u )
{
int H = inf;
if( e[u] > 0 && u != 1 && u != vertix )
{
for( int i = 1; i <= vertix; i++)
{
int x = cap[u][i] - flow[u][i];
if(x > 0 && h[i] < H)
{
H = h[i];
}
}
if( h[u] <= H)
{
h[u] = H + 1;
visit[u] = 1;
q.push_back( u );
}
}
}
void Initialize_Preflow( )
{
memset(h, 0, sizeof(h));
memset(e, 0, sizeof(e));
memset(flow, 0,sizeof(flow));
memset(visit,0, sizeof(visit));
h[1] = vertix;
visit[1] = 1;
q.push_back( 1 );
for( int i = 1; i <= vertix; i++)
{
if (cap[1][i])
{
flow[1][i] = cap[1][i];
flow[i][1] = -cap[1][i];
e[i] = cap[1][i];
e[1] = e[1] - cap[1][i];
visit[i] = 1;
q.push_back(i);
}
}
}
void solve(int x )
{
while( !q.empty() )
{
int u = q.front( );
visit[u] = 0;
q.pop_front( );
for( int i = 1; i <= vertix; i++)
{
Push(u, i);
}
Relable( u );
}
int ans = 0;
for( int i = 1; i <= vertix; i++)
{
ans += flow[1][i];
}
printf("Case %d: %d\n", x, ans);
}
int main( )
{
int a, b, c, l = 0, T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&vertix, &N);
l++;
q.clear();
memset(cap, 0, sizeof(cap));
for( int i = 1; i <= N; i++)
{
//scanf("%d%d%d",&a,&b, &c);
a = Scan();
b = Scan();
c = Scan();
cap[a][b] += c;
}
Initialize_Preflow( );
solve(l);
}
return 0;
}
/*
6
6
10
1 2 16
1 3 13
2 3 10
3 2 4
2 4 12
4 3 9
3 5 14
5 4 7
5 6 4
4 6 20
*/
posted on 2012-03-08 23:24 more think, more gains 阅读(558) 评论(0) 编辑 收藏 举报