HDU3549 最大流 裸题
EK算法 时间复杂度o(n*m*m) 因为有反向边每次bfs时间为 n*m 每次删一条边 最多m次
代码
#include<iostream>
#include<string.h>
#include<vector>
#include<stdio.h>
#include<queue>
using namespace std;
const int maxn=2e5+,inf=0x3f3f3f3f;
typedef long long ll;
struct edge
{
int from,to,c,f;
edge(int u,int v,int c,int f):from(u),to(v),c(c),f(f) {}
};
int n,m;
vector<edge> edges;
vector<int> g[maxn];
int a[maxn],p[maxn];
void init()
{
for(int i=; i<=n; i++) g[i].clear();
edges.clear();
}
void addedge(int from,int to,int c)
{
edges.push_back(edge(from,to,c,));
edges.push_back(edge(to,from,,));
int siz=edges.size();
g[from].push_back(siz-);
g[to].push_back(siz-);
}
ll maxflow(int s,int t)
{
ll flow=;
while()
{
memset(a,,sizeof(a));
queue<int> q;
q.push(s);
a[s]=inf;
while(!q.empty())
{
int x=q.front();
q.pop();
// cout<<x<<" "<<g[x].size()<<endl;
for(int i=; i<g[x].size(); i++)
{
int u=g[x][i];
edge &e=edges[u];
//cout<<e.from<<" "<<e.to<<endl;
if(!a[e.to]&&e.c>e.f)
{
p[e.to]=u; //存边
a[e.to]=min(a[x],e.c-e.f);
q.push(e.to);
}
}
if(a[t])break;
}
// cout<<a[t]<<endl; //a[t]为一次增广值
if(!a[t]) break;
for(int u=t; u!=s; u=edges[p[u]].from)//流量修改
{
edges[p[u]].f+=a[t];
edges[p[u]^].f-=a[t];
}
flow+=(ll)a[t];
}
return flow;
}
int main()
{
int t,u,v,c,f,kase=;
cin>>t;
while(t--)
{
cin>>n>>m;
init();
for(int i=; i<m; i++)
{
cin>>u>>v>>c;
addedge(u-,v-,c);
}
printf("Case %d: %d\n",kase++,maxflow(,n-));
//cout<<maxflow(0,n-1)<<endl;
}
}
Dinic 时间复杂度o(n*n*m)最多计算n-1次阻塞流 每次n*m 很松的上界
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+,mod=1e9+,inf=0x3f3f3f3f;
typedef long long ll;
struct edge
{
int from,to,c,f;
edge(int u,int v,int c,int f):from(u),to(v),c(c),f(f) {}
};
int n,m;
vector<edge> edges;
vector<int> g[maxn];
int d[maxn];//从起点到i的距离
int cur[maxn];//当前弧下标
void init()
{
for(int i=; i<=n; i++) g[i].clear();
edges.clear();
}
void addedge(int from,int to,int c) //加边 支持重边
{
edges.push_back(edge(from,to,c,));
edges.push_back(edge(to,from,,));
int siz=edges.size();
g[from].push_back(siz-);
g[to].push_back(siz-);
}
int bfs(int s,int t) //构造一次层次图
{
memset(d,-,sizeof(d));
queue<int> q;
q.push(s);
d[s]=;
while(!q.empty())
{
int x=q.front();q.pop();
for(int i=;i<g[x].size();i++)
{
edge &e=edges[g[x][i]];
if(d[e.to]<&&e.f<e.c) //d[e.to]=-1表示没访问过
{
d[e.to]=d[x]+;
q.push(e.to);
}
}
}
return d[t];
}
int dfs(int x,int a,int t) // a表示x点能接收的量
{
if(x==t||a==)return a;
int flow=,f;//flow总的增量 f一条增广路的增量
for(int &i=cur[x];i<g[x].size();i++)//cur[i] &引用修改其值 从上次考虑的弧
{
edge &e=edges[g[x][i]];
if(d[x]+==d[e.to]&&(f=dfs(e.to,min(a,e.c-e.f),t))>) //按照层次图增广 满足容量限制
{
e.f+=f;
edges[g[x][i]^].f-=f; //修改流量
flow+=f;
a-=f;
if(a==) break;
}
}
return flow;
}
int maxflow(int s,int t)
{
int flow=;
while(bfs(s,t)!=-) //等于-1代表构造层次图失败 结束
{
memset(cur,,sizeof(cur));
flow+=dfs(s,inf,t);
}
return flow;
}
int main()
{
int t,kase=;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
init();
int u,v,c,f;
for(int i=;i<m;i++)
{
scanf("%d%d%d",&u,&v,&c);
addedge(u,v,c);
}
printf("Case %d: %d\n",kase++,maxflow(,n));
}
}
ISAP gap优化版 性能比dinic 好一点
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+,mod=1e9+,inf=0x3f3f3f3f;
typedef long long ll;
struct Edge
{
int from,to,cap,flow;
Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f) {}
};
int n,m;
vector<Edge>edges;
vector<int>G[maxn];
int vis[maxn];
int d[maxn],cur[maxn];
int p[maxn],num[maxn];//比Dinic算法多了这两个数组,p数组标记父亲结点,num数组标记距离d[i]存在几个
void init()
{
for(int i=; i<=n; i++) G[i].clear();
edges.clear();
memset(d,-,sizeof(d));
}
void addedge(int from,int to,int cap)
{
edges.push_back(Edge(from,to,cap,));
edges.push_back(Edge(to,from,,));
int m=edges.size();
G[from].push_back(m-);
G[to].push_back(m-);
}
int Augumemt(int s,int t)
{
int x=t,a=inf;
while(x!=s)//找最小的残量值
{
Edge&e=edges[p[x]];
a=min(a,e.cap-e.flow);
x=edges[p[x]].from;
}
x=t;
while(x!=s)//增广
{
edges[p[x]].flow+=a;
edges[p[x]^].flow-=a;//更新反向边。
x=edges[p[x]].from;
}
return a;
}
void bfs(int t)//逆向进行bfs
{
memset(vis,,sizeof(vis));
queue<int>q;
q.push(t);
d[t]=;
vis[t]=;
while(!q.empty())
{
int x=q.front();
q.pop();
int len=G[x].size();
for(int i=; i<len; i++)
{
Edge&e=edges[G[x][i]];
if(!vis[e.from]&&e.cap>e.flow)
{
vis[e.from]=;
d[e.from]=d[x]+;
q.push(e.from);
}
}
}
} int Maxflow(int s,int t)//根据情况前进或者后退,走到汇点时增广
{
int flow=;
bfs(t);
memset(num,,sizeof(num));
for(int i=; i<=n; i++)
num[d[i]]++;
int x=s;
memset(cur,,sizeof(cur));
while(d[s]<n)
{
if(x==t)//走到了汇点,进行增广
{
flow+=Augumemt(s,t);
x=s;//增广后回到源点
}
int ok=;
for(int i=cur[x]; i<G[x].size(); i++)
{
Edge& e=edges[G[x][i]];
if(e.cap>e.flow&&d[x]==d[e.to]+)
{
ok=;
p[e.to]=G[x][i];//记录来的时候走的边,即父边
cur[x]=i;
x=e.to;//前进
break;
}
}
if(!ok)//走不动了,撤退
{
int m=n-;//如果没有弧,那么m+1就是n,即d[i]=n
for(int i=; i<G[x].size(); i++)
{
Edge& e=edges[G[x][i]];
if(e.cap>e.flow)
m=min(m,d[e.to]);
}
if(--num[d[x]]==)break;//如果走不动了,且这个距离值原来只有一个,那么s-t不连通,这就是所谓的“gap优化”
num[d[x]=m+]++;
cur[x]=;
if(x!=s)
x=edges[p[x]].from;//退一步,沿着父边返回
}
}
return flow;
} int main()
{
int t,kase=;
scanf("%d",&t);
while(t--)
{
init();
scanf("%d%d",&n,&m);
for(int i=; i<m; i++)
{
int from,to,cap;
scanf("%d%d%d",&from,&to,&cap);
addedge(from,to,cap);
}
printf("Case %d: %d\n",kase++,Maxflow(,n));
}
return ;
}
ISAP算法 详解及其他版本参见https://blog.csdn.net/guhaiteng/article/details/52433239
HDU3549 最大流 裸题的更多相关文章
- hdu Flow Problem (最大流 裸题)
最大流裸题,贴下模版 view code#include <iostream> #include <cstdio> #include <cstring> #incl ...
- POJ 1087 最大流裸题 + map
A Plug for UNIX Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 15597 Accepted: 5308 ...
- HDU-3549 最大流模板题
1.HDU-3549 Flow Problem 2.链接:http://acm.hdu.edu.cn/showproblem.php?pid=3549 3.总结:模板题,参考了 http://ww ...
- HDU 3376 && 2686 方格取数 最大和 费用流裸题
题意: 1.一个人从[1,1] ->[n,n] ->[1,1] 2.仅仅能走最短路 3.走过的点不能再走 问最大和. 对每一个点拆点限流为1就可以满足3. 费用流流量为2满足1 最大费用流 ...
- 紫书 习题 11-3 UVa 820 (最大流裸题)
注意这道题是双向边, 然后直接套模板就ok了. #include<cstdio> #include<algorithm> #include<vector> #inc ...
- POJ 2195 Going Home 最小费用流 裸题
给出一个n*m的图,其中m是人,H是房子,.是空地,满足人的个数等于房子数. 现在让每个人都选择一个房子住,每个人只能住一间,每一间只能住一个人. 每个人可以向4个方向移动,每移动一步需要1$,问所有 ...
- 【填坑】bzoj3224 splay裸题
人生第一道splay不出所料是一道裸题,一道水题,一道2k代码都不到的题 #include <cstdio> ,n,p,q; ],c[][],size[],sp[]; void rot(i ...
- tarjan讲解(用codevs1332(tarjan的裸题)讲解)
主要借助这道比较裸的题来讲一下tarjan这种算法 tarjan是一种求解有向图强连通分量的线性时间的算法.(用dfs来实现) 如果两个顶点可以相互通达,则称两个顶点强连通.如果有向图G的每两个顶点都 ...
- LCT裸题泛做
①洞穴勘测 bzoj2049 题意:由若干个操作,每次加入/删除两点间的一条边,询问某两点是否连通.保证任意时刻图都是一个森林.(两点之间至多只有一条路径) 这就是个link+cut+find roo ...
随机推荐
- spark性能优化-JVM虚拟机垃圾回收调优
1 2 3 4
- Visual studio每次build自动增加版本号
关键词:visual studio,rc file,VS_VERSION_INFO,FILEVERSION,PRODUCTVERSION 目标:希望每次在vs中编译项目时,生成的可执行程序版本号自动+ ...
- 第16周翻译:SQL Server中的事务日志管理,级别3:事务日志、备份和恢复
源自: http://www.sqlservercentral.com/articles/Stairway+Series/73779/ 作者: Tony Davis, 2011/09/07 翻译:刘琼 ...
- IE11/Flash页游白屏怎么办!立刻开启IE大地址模式!缓解浏览器白屏问题
您是否经常发现IE白屏了,具体表现为点开新网页时无法显示,只能切换标签,用任务管理器一看,内存1.2G之多. 这是因为IE11可能有内存泄露问题,内存不断增长以至于无法申请新的内存,于是IE就完蛋了! ...
- 洛谷 P1163 银行贷款
题目描述 当一个人从银行贷款后,在一段时间内他(她)将不得不每月偿还固定的分期付款.这个问题要求计算出贷款者向银行支付的利率.假设利率按月累计. 输入输出格式 输入格式: 输入文件仅一行包含三个用空格 ...
- 设计模式、SOLID原则:组件与联系
组件原则 - SRP The Single Responsibility Principle 单一责任原则 当需要修改某个类的时候原因有且只有一个.换句话说就是让一个类只做一种类型的责任,当这个类需要 ...
- Hadoop伪集群部署
环境准备 [root@jiagoushi ~]# yum -y install lrzsz 已加载插件:fastestmirror Repository 'saltstack-repo': Error ...
- Linux之常用Shell脚本总结
一.简介本文将总结一些常用的shell脚本,方便以后工作中使用. 二.shell脚本[a]定期备份mysql数据库,需结合cronb定时任务调度实现. #!/bin/bash#首先声明一些自定义变量 ...
- No-9.函数基础
函数基础 目标 函数的快速体验 函数的基本使用 函数的参数 函数的返回值 函数的嵌套调用 在模块中定义函数 01. 函数的快速体验 1.1 快速体验 所谓函数,就是把 具有独立功能的代码块 组织为一个 ...
- 在windows下.NET CORE 与Consul简单使用
0)基本概念 consul常用于服务发现 [微服务] web_Api \ \ ->注册服务 raft选举le ...