经典的最大流题POJ1273(网络流裸题)
http://poj.org/problem?id=1273
| Time Limit: 1000MS | Memory Limit: 10000K | |
| Total Submissions:87219 | Accepted: 33916 |
Description
Farmer John knows not only how many gallons of water each ditch can transport per minute but also the exact layout of the ditches, which feed out of the pond and into each other and stream in a potentially complex network.
Given all this information, determine the maximum rate at which water can be transported out of the pond and into the stream. For any given ditch, water flows in only one direction, but there might be a way that water can flow in a circle.
Input
Output
Sample Input
5 4
1 2 40
1 4 20
2 4 20
2 3 30
3 4 10
Sample Output
50 现在有m个池塘(从1到m开始编号,1为源点,m为汇点),及n条水渠,给出这n条水渠所连接的池塘和所能流过的水量,求水渠中所能流过的水的最大容量.一道基础的最大流题目。 ——其他练习题 POJ3436 、
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <bitset>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <sstream>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll inff = 0x3f3f3f3f3f3f3f3f;
#define FOR(i,a,b) for(int i(a);i<=(b);++i)
#define FOL(i,a,b) for(int i(a);i>=(b);--i)
#define REW(a,b) memset(a,b,sizeof(a))
#define inf int(0x3f3f3f3f)
#define si(a) scanf("%d",&a)
#define sl(a) scanf("%I64d",&a)
#define sd(a) scanf("%lf",&a)
#define ss(a) scanf("%s",a)
#define mod ll(998244353)
#define pb push_back
#define eps 1e-6
#define lc d<<1
#define rc d<<1|1
#define Pll pair<ll,ll>
#define P pair<int,int>
#define pi acos(-1)
const int N=,M=;
int head[N],tot,n,m,a,b,c;
struct node{
int next,c,to;}e[M];
struct max_flow{
int S,T,n;
int lev[N],q[N],cur[N],f;
void init(int _s,int _t)
{
tot=;S=_s,T=_t,n=T+;
FOR(i,,n) head[i]=-;
}
void add(int a,int b,int c)
{
e[tot].next=head[a];
e[tot].to=b;
e[tot].c=c;
head[a]=tot++;
}
void Add(int a,int b,int c)
{
add(a,b,c);
add(b,a,);
}
int bfs()
{
FOR(i,,n) lev[i]=;
lev[S]=,f=,q[f++]=S;
FOR(i,,f-)
{
int u=q[i];
for(int i=head[u];i!=-;i=e[i].next)
if(lev[e[i].to]==&&e[i].c>)
{
int to=e[i].to;
lev[to]=lev[u]+;
q[f++]=to;
if(to==T) return ;
}
}
return ;
}
int dfs(int u,int f)
{
if(u==T) return f;
int tag=,c;
for(int &i=cur[u];i!=-;i=e[i].next)
{
int to=e[i].to;
if(e[i].c>&&lev[to]==lev[u]+)
{
c=dfs(to,min(f-tag,e[i].c));
e[i].c-=c;
e[i^].c+=c;
tag+=c;
if(tag==f) return tag;
}
}
return tag;
}
int slove()
{
int ans=;
while(bfs())
{
FOR(i,,n) cur[i]=head[i];
ans+=dfs(S,inf);
}
return ans;
}
}flow;
int main()
{
cin.tie();
cout.tie();
while(~scanf("%d%d",&m,&n))
{
flow.init(,n);
while(m--)
{
si(a),si(b),si(c);
flow.Add(a,b,c);
}
cout<<flow.slove()<<endl;
}
return ;
}
https://blog.csdn.net/huzhengnan/article/details/7766446
最大流的一些板子
https://blog.csdn.net/wjf_wzzc/article/details/24820525
sap:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<string>
#include<queue>
#include<algorithm>
using namespace std; const int N=;
const int M=;
const int inf=0xfffffff; int n,m,cnt; struct Edge{
int v , cap , next;
} edge[M]; int head[N],pre[N],d[N],numd[N];//分别为链表的头指针,每个点的前驱,每个点的d值,以及标号为d[i] 的点的个数
int cur_edge[N];//从每个点出发满足d[i] = d[j] + 1的边的地址 , 插入边时的计数,源点与汇点 void addedge(int u,int v,int c){ edge[cnt].v = v;
edge[cnt].cap = c;
edge[cnt].next = head[u];
head[u] = cnt++; edge[cnt].v = u;
edge[cnt].cap = ;
edge[cnt].next = head[v];
head[v] = cnt++;
} void bfs(int s){ //先用广度优先算出每个点的d值
memset(numd,,sizeof(numd));
for(int i=; i<=n; i++)
numd[ d[i] = n ]++;
d[s] = ;
numd[n]--;
numd[]++;
queue<int> Q;
Q.push(s); while(!Q.empty()){
int v=Q.front();
Q.pop(); int i=head[v];
while(i != -){
int u=edge[i].v; if(d[u]<n){
i=edge[i].next;
continue ;
} d[u]=d[v]+;
numd[n]--;
numd[d[u]]++;
Q.push(u);
i=edge[i].next;
}
}
} int SAP(int s,int t){
for(int i = ; i <= n; i++)
cur_edge[i] = head[i]; //当前满足d[i] = d[j] + 1的边的为第一条边
int max_flow=;
bfs(t);
int u = s ;//从源点搜一条到汇点的增广路
while(d[s]<n){//就算所有的点连成一条线源点的d值也是最多是n-1
if(u == t){//如果找到一条增广路径
int cur_flow = inf,neck;//找到那条瓶颈边
for(int from = s; from != t; from = edge[cur_edge[from]].v){
if(cur_flow > edge[cur_edge[from]].cap){
neck = from;
cur_flow = edge[cur_edge[from]].cap;
}
} for(int from = s; from != t; from = edge[cur_edge[from]].v){ //修改增广路上的边的容量
int tmp = cur_edge[from];
edge[tmp].cap -= cur_flow;
edge[tmp^].cap += cur_flow;
}
max_flow += cur_flow;//累加计算最大流
u = neck;//下一次搜索直接从瓶颈边的前一个节点搜起
} int i;
for(i = cur_edge[u]; i != -; i = edge[i].next) //从当前点开始找一条允许弧
if(edge[i].cap && d[u] == d[edge[i].v]+)//如果找到跳出循环
break; if(i!=-){//找到一条允许弧
cur_edge[u] = i;//从点u出发的允许弧的地址
pre[edge[i].v] = u;//允许弧上下一个点的前驱为u
u = edge[i].v;//u变成下一个点继续搜直到搜出一条增广路
}
else{//如果没有搜到允许弧
numd[d[u]]--; //d[u]将被修改所以numd[d[u]]减一
if(!numd[d[u]]) break; //如果没有点的d值为d[u]则不可能再搜到增广路结束搜索
cur_edge[u] = head[u]; //当前点的允许弧为第一条边
int tmp = n;
for(int j = head[u]; j != -; j = edge[j].next) //搜与u相连的点中d值最小的
if(edge[j].cap && tmp > d[edge[j].v])
tmp = d[edge[j].v]; d[u] = tmp+; //修改d[u]
numd[d[u]]++;
if(u != s)
u = pre[u];//从u的前驱搜,因为从u没有搜到允许弧
}
}
return max_flow;
}
inline void pre_init(){
cnt = ;
memset(head, -, sizeof head);
} void mapping(){
int u, v, w;
for(int i = ; i <= m; ++i){
scanf("%d %d %d", &u, &v, &w);
addedge(u, v, w);
}
} int main(){
while(~scanf("%d%d",&m,&n)){
pre_init();
mapping();
int s,t;
s = ;t = n;
int ans = SAP(s,t);
printf("%d\n",ans);
}
return ;
}
dinic:
//dinic #include <algorithm>
#include <iostream>
#include <string.h>
#include <cstdio>
#include <queue>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = ;
const int maxm = maxn*maxn;
struct node{int w; int v, next;} edge[maxm];
int pre[maxn], rec[maxn], head[maxn], block[maxn];
int dis[maxn];
int n, m, no;
int S, T;
queue<int> q;
inline void init(){
no = ;
memset(head, -, sizeof head);
}
inline void add(int u, int v, int w){
edge[no].v = v; edge[no].w = w;
edge[no].next = head[u]; head[u] = no++;
edge[no].v = u; edge[no].w = ;
edge[no].next = head[v]; head[v] = no++;
}
void reset(int S, int T){
memset(dis, 0x3f, sizeof dis);
memset(block, , sizeof block);
q.push(S); dis[S] = ;
while(!q.empty()){
int top = q.front(); q.pop();
for(int k = head[top]; k != -; k = edge[k].next)
if(dis[edge[k].v] == inf && edge[k].w)
dis[edge[k].v] = dis[top]+, q.push(edge[k].v);
}
}
int dinic(int S, int T){
int ans = , flow = inf;
int top = S;
reset(S, T); pre[S] = S;
while(dis[T] != inf){
int k, tmp;
for(k = head[top]; k != -; k = edge[k].next){
if(edge[k].w && dis[edge[k].v]==dis[top]+ &&
!block[edge[k].v]) break;
}
if(k != -){
tmp = edge[k].v;
flow = min(flow, edge[k].w);
pre[tmp] = top, rec[tmp] = k;
top = tmp;
if(top == T){
ans += flow; tmp = -;
for(; top != S; top = pre[top]){
edge[rec[top]].w -= flow;
edge[rec[top]^].w += flow;
if(!edge[rec[top]].w) tmp = top;
}
flow = inf;
if(tmp != -){
top = pre[tmp];
for(; top != S; top = pre[top])
flow = min(flow, edge[rec[top]].w);
top = pre[tmp];
}
}
}
else{
block[top] = ;
top = pre[top];
if(block[S]) reset(S, T);
}
}
return ans;
}
void mapping(){
int u, v, w;
for(int i = ; i <= m; ++i){
scanf("%d %d %d", &u, &v, &w);
add(u, v, w);
}
}
int main(){
while(~scanf("%d %d", &m, &n)){
S = , T = n;
init();
mapping();
printf("%d\n", dinic(S, T));
}
return ;
}
感谢https://www.cnblogs.com/Asumi/p/9751117.html
【最大流之Dinic算法】POJ1273 【 & 当前弧优化 & 】
https://www.cnblogs.com/DF-yimeng/p/8583698.html
//dinic
#include <algorithm>
#include <iostream>
#include <string.h>
#include <cstdio>
#include <queue>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = ;
const int maxm = maxn*maxn;
struct node
{
int w;
int v, next;
} edge[maxm];
int pre[maxn], rec[maxn], head[maxn], block[maxn];
int dis[maxn];
int n, m, no;
int S, T;
queue<int> q;
inline void init()
{
no = ;
memset(head, -, sizeof head);
}
inline void add(int u, int v, int w)
{
edge[no].v = v;
edge[no].w = w;
edge[no].next = head[u];
head[u] = no++;
edge[no].v = u;
edge[no].w = ;
edge[no].next = head[v];
head[v] = no++;
}
void reset(int S, int T)
{
memset(dis, 0x3f, sizeof dis);
memset(block, , sizeof block);
q.push(S);
dis[S] = ;
while(!q.empty())
{
int top = q.front();
q.pop();
for(int k = head[top]; k != -; k = edge[k].next) if(dis[edge[k].v] == inf && edge[k].w) dis[edge[k].v] = dis[top]+, q.push(edge[k].v);
}
}
int dinic(int S, int T)
{
int ans = , flow = inf;
int top = S;
reset(S, T);
pre[S] = S;
while(dis[T] != inf)
{
int k, tmp;
for(k = head[top]; k != -; k = edge[k].next)
{
if(edge[k].w && dis[edge[k].v]==dis[top]+ && !block[edge[k].v]) break;
}
if(k != -)
{
tmp = edge[k].v;
flow = min(flow, edge[k].w);
pre[tmp] = top, rec[tmp] = k;
top = tmp;
if(top == T)
{
ans += flow;
tmp = -;
for(; top != S; top = pre[top])
{
edge[rec[top]].w -= flow;
edge[rec[top]^].w += flow;
if(!edge[rec[top]].w) tmp = top;
}
flow = inf;
if(tmp != -)
{
top = pre[tmp];
for(; top != S; top = pre[top]) flow = min(flow, edge[rec[top]].w);
top = pre[tmp];
}
}
}
else
{
block[top] = ;
top = pre[top];
if(block[S]) reset(S, T);
}
}
return ans;
}
void mapping()
{
int u, v, w;
for(int i = ; i <= m; ++i)
{
scanf("%d %d %d", &u, &v, &w);
add(u, v, w);
}
}
int main()
{
while(~scanf("%d %d", &m, &n))
{
S = , T = n;
init();
mapping();
printf("%d\n", dinic(S, T));
}
return ;
}
经典的最大流题POJ1273(网络流裸题)的更多相关文章
- 【费用流】【网络流24题】【cogs 739】运输问题
739. [网络流24题] 运输问题 ★★ 输入文件:tran.in 输出文件:tran.out 简单对照 时间限制:1 s 内存限制:128 MB «问题描写叙述: «编程任务: 对于给定的m 个仓 ...
- 【费用流】【网络流24题】【P4013】 数字梯形问题
Description 给定一个由 \(n\) 行数字组成的数字梯形如下图所示. 梯形的第一行有 \(m\) 个数字.从梯形的顶部的 \(m\) 个数字开始,在每个数字处可以沿左下或右下方向移动,形成 ...
- 【费用流】【网络流24题】【P1251】 餐巾计划问题
Description 一个餐厅在相继的 \(N\) 天里,每天需用的餐巾数不尽相同.假设第 \(i\) 天需要 \(r_i\)块餐巾.餐厅可以购买新的餐巾,每块餐巾的费用为 \(p\) 分;或者把旧 ...
- 【费用流】【网络流24题】【P4014】 分配问题
Description 有 \(n\) 件工作要分配给 \(n\) 个人做.第 \(i\) 个人做第 \(j\) 件工作产生的效益为 \(C_{i,j}\) .试设计一个将 \(n\) 件工作分配给 ...
- 【生活没有希望】poj1273网络流大水题
你不能把数据规模改大点吗= =我优化都不加都过了 #include <cstdio> #define INF 2147483647 int n,m,ans,x,y,z,M; ],l[],f ...
- poj1273 网络流入门题 dinic算法解决,可作模板使用
Drainage Ditches Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 62078 Accepted: 2384 ...
- HDU-1532 网络流裸题
HDU-1532 题意简单的来说就是从1点到n点,最大的流量是多少. 代码: #include<bits/stdc++.h> using namespace std; #define Fo ...
- 【最大流/二分图匹配】【网络流24题】【P3254】 圆桌问题
Description 假设有来自m 个不同单位的代表参加一次国际会议.每个单位的代表数分别为ri (i =1,2,--,m). 会议餐厅共有n 张餐桌,每张餐桌可容纳ci (i =1,2,--,n) ...
- hdu Flow Problem (最大流 裸题)
最大流裸题,贴下模版 view code#include <iostream> #include <cstdio> #include <cstring> #incl ...
随机推荐
- 文本检错——中文拼写检查工具FASPell
最近因为相关项目需要考虑中文文本检错,然后就发现了爱奇艺发布的号称SOTA的FASPell已经开源代码,所以开始着手实现. 检错思想两步:一,掩码语言模型(MLM)产生候选字符:二,CSD过滤候选字符 ...
- 【hackerrank】Placements
题目如下: You are given three tables: Students, Friends and Packages. Students contains two columns: ID ...
- 【leetcode】523. Continuous Subarray Sum
题目如下: 解题思路:本题需要用到这么一个数学定理.对于任意三个整数a,b,k(k !=0),如果 a%k = b%k,那么(a-b)%k = 0.利用这个定理,我们可以对数组从头开始进行求和,同时利 ...
- Angular前端开源框架
1. 项目框架介绍 本项目采用了开源项目ngx-admin作为脚手架.基于Angular 8 +,Bootstrap 4+和Nebular,ngx-admin是最受欢迎的后台管理模板,是用于个人和商 ...
- python+requests接口自动化框架
为什么要做接口自动化框架 1.业务与配置的分离 2.数据与程序的分离:数据的变更不影响程序 3.有日志功能,实现无人值守 4.自动发送测试报告 5.不懂编程的测试人员也可以进行测试 正常接口测试的流程 ...
- linux运维、架构之路-MySQL(二)
一.SQL语句实战 1.DDL语句——库管理 ①查看数据库 show databases; show databases like 'word%';#模糊查询数据库 ②创建数据库 create dat ...
- 【PowerOJ1746&网络流24题】航空路线问题(费用流)
题意: 思路: [问题分析] 求最长两条不相交路径,用最大费用最大流解决. [建模方法] 把第i个城市拆分成两个顶点<i.a>,<i.b>. 1.对于每个城市i,连接(< ...
- 爬虫小例1:ajax形式的网页数据的抓取
---恢复内容开始--- 下面记录如何抓取ajax形式加载的网页数据: 目标:获取“https://movie.douban.com/typerank?type_name=%E5%89%A7%E6%8 ...
- NOIP2012 洛谷P1083 借教室
传送门 题意:有一些学(xian)生(quan)要借教室.在n天内,第i天学校有ri个教室.有m份订单,每份订单有三个数值dj,sj,tj,分别表示这个订单从第sj天开始到第tj天结束(包括端点),每 ...
- fedora23深度配置gnome系统环境, 如设置ibus的面板字体大小 以及gedit 自动探测文件字符编码fileencodings
除了系统桌面gnome, 以及gnome应用程序自带的preferences, 还有很多设置, 没有在preferences, 而是被深度地隐藏在系统中, 这时, 需要安装 dconf-tools: ...