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