点这里 |
---|
题意: 给定一个有向图,求点1到点n的最大流。
题解: 算法详见Dinic算法研究总结
EK模板
#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 300;
int T, n, m, k;
int pre[N], G[N][N]; //记录前驱节点、存图
int bfs(int s, int t){
int flow[N]; //到节点i的流量
memset(pre, -1, sizeof pre); //重置前驱节点
flow[s] = inf; pre[s] = 0; //源点的容量无限
queue<int> Q; Q.push(s);
while(!Q.empty()){
int u = Q.front(); Q.pop();
if(u == t) break;
for(int i = 1; i <= t; i++)
if(i != s && G[u][i] > 0 && pre[i] == -1){ //保证i不是起点,i没有去过,i还有残留容量
pre[i] = u;
Q.push(i);
flow[i] = min(flow[u], G[u][i]);
}
}
if(pre[t] == -1) return -1;
return flow[t];
}
int maxflow(int s, int t){
int Maxflow = 0;
while(1){
int flow = bfs(s, t);
if(flow == -1) break;
int cur = t;
while(cur != s){
int fa = pre[cur];
G[fa][cur] -= flow;
G[cur][fa] += flow; //更新残留容量
cur = fa;
}
Maxflow += flow; //这条增广路的流量汇入汇点
}
return Maxflow;
}
int main(){
scanf("%d", &T);
while(T--){
memset(G, 0, sizeof G);
scanf("%d%d", &n, &m);
while(m--){
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
G[u][v] += w; //可能有重边
}
printf("Case %d: %d\n", ++k, maxflow(1, n));
}
return 0;
}
Dinic模板
#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 20;
const int M = 1005;
int T, n, m, k;
int s, t, cnt;
int cur[N];
int head[N];
int depth[N];
struct edge{ int v, w, next;} e[2 * M];
void add(int u, int v, int w){ e[cnt].v = v, e[cnt].w = w, e[cnt].next = head[u], head[u] = cnt++;}
void addedge(int u, int v, int w){ add(u, v, w); add(v, u, 0);} //有向图,注意加的第二条边
void init(){ s = 1, t = n, cnt = 0; for(int i = 1; i < N; i++) head[i] = -1;}
bool bfs(){
for(int i = 1; i <= t; i++) depth[i] = 0;
queue<int> Q;
Q.push(s); depth[s] = 1;
while(!Q.empty()){
int u = Q.front(); Q.pop();
for(int i = head[u]; ~i; i = e[i].next){
int v = e[i].v, w = e[i].w;
if(depth[v] == 0 && w > 0){ //点v没有去过并且还有残留容量
depth[v] = depth[u] + 1;
Q.push(v);
}
}
}
if(depth[t] > 0) return 1;
return 0;
}
int dfs(int u, int flow){
if(u == t) return flow;
for(int& i = cur[u]; ~i; i = e[i].next){ //&符号,改变i的同时也会改变cur[u]
int v = e[i].v, w = e[i].w;
if(depth[v] == depth[u] + 1 && w != 0){ //点v没有去过并且还有残留容量
int minflow = dfs(v, min(flow, w));
if(minflow > 0){
e[i].w -= minflow;
e[i ^ 1].w += minflow; //更新残留容量
return minflow;
}
}
}
return 0;
}
int Dinic(){
int ans = 0;
while(bfs()){
for(int i = 1; i <= t; i++) cur[i] = head[i];
while(int d = dfs(s, inf)) ans += d;
}
return ans;
}
int main(){
scanf("%d", &T);
while(T--){
scanf("%d%d", &n, &m);
init();
while(m--){
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
addedge(u, v, w);
}
printf("Case %d: %d\n", ++k, Dinic());
}
return 0;
}