P3376 (最大流 dinic)

Posted jpphy0

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3376 (最大流 dinic)相关的知识,希望对你有一定的参考价值。

问题

P3376 - https://www.luogu.com.cn/problem/P3376

分析

代码

简洁(无当前弧优化)【81MS】

#include<bits/stdc++.h>
using namespace std;
const int inf = 0x7fffffff;
const int MXN = 105, MXE = 10010;
int tot, n, m, k, head[MXN<<1], d[MXN<<1];   // 前向星
struct Edge{int to, nxt, w;}edge[MXE]; // 图边
void addEdge(int u, int v, int w){ // 加边
	Edge &e = edge[++tot];
	e.to = v, e.nxt = head[u], e.w = w, head[u] = tot;
}
void add(int u, int v, int w){ // 加原边 和 反向边
	addEdge(u, v, w), addEdge(v, u, 0);
}
bool bfs(int s, int t){ // 源点、汇点
	int lst;
	queue<int> q;
	memset(d, 0, sizeof d);
	q.push(s), d[s] = 1;
	while(!q.empty()){
		lst = q.front(), q.pop();
		for(int i = head[lst]; ~i; i = edge[i].nxt){
			if(edge[i].w && !d[edge[i].to]){
				q.push(edge[i].to);
				d[edge[i].to] = d[lst]+1;
				if(edge[i].to == t) return true;
			}
		}		
	}
	return false;
}
int dfs(int s, int t, int lim){// 多路增广
	if(s == t) return lim;
	int rest = lim; // 后续增广路的流量上界
	for(int flow, i = head[s]; ~i && rest; i = edge[i].nxt){
		if(edge[i].w && d[edge[i].to] == d[s]+1){
			flow = dfs(edge[i].to, t, min(edge[i].w, rest));
			if(!flow) d[edge[i].to] = 0;
			edge[i].w -= flow, edge[i^1].w += flow, rest -= flow;
		}
	}
	return lim - rest;
}
long long dinic(int s, int t){ // 源点、汇点
	long long flow, maxflow = 0;
	while(bfs(s, t)) while(flow = dfs(s, t, inf)) maxflow += flow;
	return maxflow;
}
int main(){
	int s, t, u, v, w;
	scanf("%d%d%d%d", &n, &m, &s, &t);
	tot = 1, memset(head, -1, sizeof head);
	for(int i = 1; i <= m; ++i) scanf("%d%d%d", &u, &v, &w), add(u, v, w); 
	printf("%lld\\n", dinic(s, t));	
    return 0;
}

当前弧优化【871MS】

#include<bits/stdc++.h>
using namespace std;
const int inf = 0x7fffffff;
const int MXN = 105, MXE = 10010;
int tot, n, m, k, head[MXN<<1], d[MXN<<1], cur[MXN<<1];
struct Edge{int to, nxt, w;}edge[MXE]; // 图边
void addEdge(int u, int v, int w){ // 加边
	Edge &e = edge[++tot];
	e.to = v, e.nxt = head[u], e.w = w, head[u] = tot;
}
void add(int u, int v, int w){ // 加原边 和 反向边
	addEdge(u, v, w), addEdge(v, u, 0);
}
bool bfs(int s, int t){ // 源点、汇点
	int lst;
	queue<int> q;
	memset(d, 0, sizeof d);
	q.push(s), d[s] = 1, cur[s] = head[s];
	while(!q.empty()){
		lst = q.front(), q.pop();
		for(int i = head[lst]; ~i; i = edge[i].nxt){
			if(edge[i].w && !d[edge[i].to]){
				q.push(edge[i].to);
				cur[edge[i].to] = head[edge[i].to];
				d[edge[i].to] = d[lst]+1;
				if(edge[i].to == t) return true;
			}
		}		
	}
	return false;
}
int dfs(int s, int t, int lim){// 多路增广
	if(s == t) return lim;
	int flow, i, rest = lim; // 后续增广路的流量上界
	for(i = cur[s]; ~i && rest; i = edge[i].nxt){
		if(edge[i].w && d[edge[i].to] == d[s]+1){
			flow = dfs(edge[i].to, t, min(edge[i].w, rest));
			if(!flow) d[edge[i].to] = 0;
			edge[i].w -= flow, edge[i^1].w += flow, rest -= flow;
		}
	}
	cur[s] = i;
	return lim - rest;
}
long long dinic(int s, int t){ // 源点、汇点
	long long flow, maxflow = 0;
	while(bfs(s, t)) while(flow = dfs(s, t, inf)) maxflow += flow;
	return maxflow;
}
int main(){
	int s, t, u, v, w;
	scanf("%d%d%d%d", &n, &m, &s, &t);
	tot = 1, memset(head, -1, sizeof head);
	for(int i = 1; i <= m; ++i) scanf("%d%d%d", &u, &v, &w), add(u, v, w); 
	printf("%lld\\n", dinic(s, t));	
    return 0;
}

以上是关于P3376 (最大流 dinic)的主要内容,如果未能解决你的问题,请参考以下文章

洛谷P3376模板网络最大流  Dinic模板

[洛谷 P3376] 网络最大流 | 模板 (Dinic算法) 入门

[洛谷P3376]模板网络最大流

P3376 模板网络最大流(luogu)

P3376 模板网络最大流——————Q - Marriage Match IV(最短路&最大流)

洛谷 P3376 模板网络最大流