hdu 3549 Flow Problem

acm.hdu.edu.cn/showproblem.php?pid=3549

网络流之最大流水题。利用Dinic算法实现。

因为层次图中增广路径长度随阶段而严格递增。因此,对于有n个点的流量网络,在最短路径增值算法中,最多有n个阶段。O(n^2*m)。

邻接矩阵+STL

//4134MS
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>

using namespace std;

const int MAX = 2050;
const int INF = 1e9;

int map[MAX][MAX],level[MAX],N,M;

queue <int> Q;
bool BFS(){
    memset(level, -1, sizeof(level));
    while(!Q.empty()) Q.pop();
    level[1] = 0;
    Q.push(1);
    while(!Q.empty()){
        int u = Q.front();
        Q.pop();
        for(int i=1; i<=M; i++){
            if(level[i] == -1 && map[u][i] > 0){
                level[i] = level[u] + 1;
                Q.push(i);
            }
        }
    }
    if(level[M] > 0) return true;
    return false;
}

int DFS(int id, int minflow){
    if(id == M) return minflow;
    int a = 0;
    for(int i=1; i<=M; i++){
        if(map[id][i] && level[i] == level[id] + 1
            && (a = DFS(i, min(map[id][i], minflow)))){
            map[id][i] -= a;
            map[i][id] += a;
            return a;
        }
    }
    return 0;
}

int main(){
    int cas,t = 0;
    scanf("%d",&cas);
    while(cas--){
        scanf("%d%d",&M,&N);
        memset(map, 0, sizeof(map));
        int u,v,cap;
        for(int i=0; i<N; i++){
            scanf("%d%d%d",&u,&v,&cap);
            map[u][v] += cap;
        }
        int tmp, ans = 0;
        while(BFS()){
            while(tmp = DFS(1, INF)) ans += tmp;
        }
        printf("Case %d: ",++t);
        printf("%d\n",ans);
    }
    return 0;
}
邻接矩阵+手写队列

//3775MS
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>

using namespace std;

const int MAX = 2000;
const int INF = 1e9;

int map[MAX][MAX],level[MAX],N,M;
int Q[MAX],head,tail;

bool BFS(){
    memset(level, -1, sizeof(level));
    level[1] = 0;
    head = 0, tail = 1;
    Q[1] = 1;
    while(head < tail){
        int u = Q[++head];
        for(int i=1; i<=M; i++){
            if(level[i] == -1 && map[u][i] > 0){
                level[i] = level[u] + 1;
                Q[++tail] = i;
            }
        }
    }
    if(level[M] > 0) return true;
    return false;
}

int DFS(int id, int minflow){
    if(id == M) return minflow;
    int a = 0;
    for(int i=1; i<=M; i++){
        if(map[id][i] && level[i] == level[id] + 1
            && (a = DFS(i, min(map[id][i], minflow)))){
            map[id][i] -= a;
            map[i][id] += a;
            return a;
        }
    }
    return 0;
}

int main(){
    int cas,t = 0;
    scanf("%d",&cas);
    while(cas--){
        scanf("%d%d",&M,&N);
        memset(map, 0, sizeof(map));
        int u,v,cap;
        for(int i=0; i<N; i++){
            scanf("%d%d%d",&u,&v,&cap);
            map[u][v] += cap;
        }
        int tmp, ans = 0;
        while(BFS()){
            while(tmp = DFS(1, INF)) ans += tmp;
        }
        printf("Case %d: ",++t);
        printf("%d\n",ans);
    }
    return 0;
}

邻接表+手写队列

//C++ 296MS
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>

using namespace std;

const int M = 2500000;
const int INF = 1e9;
const int N = 2050;


int head[N],cnt;//邻接表
int Q[N],h,t;//手写队列
int dis[N];//层次图
int S,T;//源点 汇点

struct edge{
	int v,c,next;
}node[M];

void Init(){//邻接表的初始化
	cnt = 0;
	memset(head, -1, sizeof(head));
}

void addedge(int u, int v, int c){///邻接表加边(不需要考虑重边的问题,但是如果使用vector实现需考虑重边)
	node[cnt].v = v;
	node[cnt].c = c;
	node[cnt].next = head[u];
	head[u] = cnt++;
}

bool BFS(){
	memset(dis, -1, sizeof(dis));
	h = 0, t = 1,Q[1] = S;
        dis[S] = 0;
        while(h < t){
		int u = Q[++h];
		for(int i=head[u]; i!=-1; i=node[i].next){
			int v = node[i].v;
			if(node[i].c > 0 && dis[v] == -1){
				dis[v] = dis[u] + 1;
				Q[++t] = v;
				if(v == T) return 1;
			}
		}
	}
	return 0;//如果层次图中没有汇点 增广过程结束
}

int DFS(int id, int minflow){
	if(id == T) return minflow;
	int a = 0;//这是递归的初始化过程
	for(int i=head[id]; i!=-1; i=node[i].next){
		int v = node[i].v;
		if(node[i].c > 0 && dis[v] == dis[id] + 1
			&& (a = DFS(v, min(minflow, node[i].c)))){
			node[i].c -= a;
			node[i^1].c += a;//i^1代表其反向边
			return a;
		}
	}
	return 0;
}


int main(){
    int cas,t = 0;
    scanf("%d",&cas);
    while(cas--){
    	int n,m;
        scanf("%d%d",&n,&m);
        Init();
        int u,v,cap;
        for(int i=0; i<m; i++){
            scanf("%d%d%d",&u,&v,&cap);
            addedge(u,v,cap);
            addedge(v,u,0);//加入反向边
        }
        S = 1, T = n;
        int tmp, ans = 0;
        while(BFS()){//条件不满足即增广过程的结束
            while(tmp = DFS(1, INF)) ans += tmp;
        }
        printf("Case %d: ",++t);
        printf("%d\n",ans);
    }
    return 0;
}






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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值