Dinic最大流 || Luogu P3376 【模板】网络最大流

博客给出了网络最大流的模板代码,代码作者为AlenaNuna,转载自https://www.cnblogs.com/AlenaNuna/p/10957576.html 。

题面:【模板】网络最大流

代码:

 1 #include<cstring>
 2 #include<cstdio>
 3 #include<iostream>
 4 #define min(a,b) ((a)<(b)?(a):(b))
 5 using namespace std;
 6 inline int rd(){
 7     int x=0,f=1;char c=getchar();
 8     while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
 9     while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
10     return f*x;
11 }
12 const int maxn=(1e4)+50,maxm=(1e5)+50;
13 int num_edge=-1,edge_head[maxn],N,M,S,T,w,u,v,Q[maxn<<1],f1,f2,Dep[maxn],Cur[maxn];
14 struct Edge{int to,nx,dis;}edge[maxm<<1];
15 inline void Add_edge(int from,int to,int dis){
16     edge[++num_edge].nx=edge_head[from];
17     edge[num_edge].to=to;
18     edge[num_edge].dis=dis;
19     edge_head[from]=num_edge;
20     return;
21 }
22 inline bool Bfs(){
23     memset(Dep,0,sizeof(Dep));
24     Dep[S]=1;
25     f1=f2=1;
26     Q[f2++]=S;
27     while(f1<f2){
28         int x=Q[f1++];
29         for(int i=edge_head[x];i!=-1;i=edge[i].nx){
30             int y=edge[i].to;
31             if(edge[i].dis&&Dep[y]==0){
32                 Dep[y]=Dep[x]+1;
33                 Q[f2++]=y;
34             }
35         }
36     }
37     if(Dep[T])return 1;
38     return 0;
39 }
40 inline int Dfs(int x,int fw){
41     if(x==T)return fw;
42     for(int &i=Cur[x];i!=-1;i=edge[i].nx){
43         int y=edge[i].to;
44         if(Dep[y]==Dep[x]+1&&edge[i].dis){
45             int p=Dfs(y,min(fw,edge[i].dis));
46             if(p>0){
47                 edge[i].dis-=p;
48                 edge[i^1].dis+=p;
49                 return p;
50             }
51         }
52     }
53     return 0;
54 }
55 inline int Dinic(){
56     int ans=0;
57     while(Bfs()){
58         for(int i=1;i<=N;i++)Cur[i]=edge_head[i];
59         while(int k=Dfs(S,1<<30))ans+=k;
60     }
61     return ans;
62 }
63 int main(){
64     memset(edge_head,-1,sizeof(edge_head));
65     N=rd();M=rd();S=rd();T=rd();
66     for(int i=1;i<=M;i++){
67         u=rd();v=rd();w=rd();
68         Add_edge(u,v,w);
69         Add_edge(v,u,0);
70     }
71     printf("%d\n",Dinic());
72     return 0;
73 }

By:AlenaNuna

转载于:https://www.cnblogs.com/AlenaNuna/p/10957576.html

# P1004 [NOIP 2000 提高组] 方格取数 ## 题目背景 NOIP 2000 提高组 T4 ## 题目描述 设有 $N \times N$ 的方格图 $(N \le 9)$,我们将其中的某些方格中填入正整数,而其他的方格中则放入数字 $0$。如下图所示(见样例): ![](https://cdn.luogu.com.cn/upload/image_hosting/0bpummja.png) 某人从图的左上角的 $A$ 点出发,可以向下行走,也可以向右走,直到到达右下角的 $B$ 点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字 $0$)。 此人从 $A$ 点到 $B$ 点共走两次,试找出 $2$ 条这样的路径,使得取得的数之和为最大。 ## 输入格式 输入的第一行为一个整数 $N$(表示 $N \times N$ 的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的 $0$ 表示输入结束。 ## 输出格式 只需输出一个整数,表示 $2$ 条路径上取得的最大的和。 ## 输入输出样例 #1 ### 输入 #1 ``` 8 2 3 13 2 6 6 3 5 7 4 4 14 5 2 21 5 6 4 6 3 15 7 2 14 0 0 0 ``` ### 输出 #1 ``` 67 ``` ## 说明/提示 数据范围:$1\le N\le 9$。这是我的代码,用网络流完成:#include <bits/stdc++.h> using namespace std; struct Dinic { struct Edge { int to, cap, rev; }; int n, s, t; vector< vector<Edge> > g; vector<int> level, it; Dinic(int n): n(n), g(n), level(n), it(n) {} void addEdge(int u, int v, int c) { Edge a{v, c, (int)g[v].size()}; Edge b{u, 0, (int)g[u].size()}; g[u].push_back(a); g[v].push_back(b); } bool bfs() { fill(level.begin(), level.end(), -1); queue<int> q; level[s] = 0; q.push(s); while (!q.empty()) { int u = q.front(); q.pop(); for (auto &e : g[u]) { if (e.cap > 0 && level[e.to] < 0) { level[e.to] = level[u] + 1; q.push(e.to); } } } return level[t] >= 0; } int dfs(int u, int f) { if (u == t) return f; for (int &i = it[u]; i < (int)g[u].size(); ++i) { auto &e = g[u][i]; if (e.cap > 0 && level[e.to] == level[u] + 1) { int ret = dfs(e.to, min(f, e.cap)); if (ret > 0) { e.cap -= ret; g[e.to][e.rev].cap += ret; return ret; } } } return 0; } int maxf(int S, int T) { s = S; t = T; int flow = 0, inf = 1e9; while (bfs()) { fill(it.begin(), it.end(), 0); while (int f = dfs(s, inf)) flow += f; } return flow; } }; struct EdgeInput { int u, v; int w; }; int main() { int N, P, T = 2; cin>> N ; vector<EdgeInput> edges(P); vector<int> weights; weights.reserve(P); for (int i = 0; ; ++i) { int u, v, w; cin >> u >> v >> w; if(u==0&&v==0&&w==0){ break; } edges[i] = {u - 1, v - 1, w}; weights.push_back(w); } sort(weights.begin(), weights.end()); weights.erase(unique(weights.begin(), weights.end()), weights.end()); auto feasible = [&](int W)->bool { Dinic dinic(N); for (auto &e : edges) { if (e.w <= W) { dinic.addEdge(e.u, e.v, 1); dinic.addEdge(e.v, e.u, 1); } } int f = dinic.maxf(0, N - 1); return f >= T; }; int left = 0, right = (int)weights.size() - 1, ans = weights.back(); while (left <= right) { int mid = (left + right) >> 1; if (feasible(weights[mid])) { ans = weights[mid]; right = mid - 1; } else { left = mid + 1; } } cout << ans << "\n"; return 0; }
09-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值