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 ...
随机推荐
- FPGA内部RAM的初始化
Altera的RAM初始化文件格式是mif和hex. QuartusII自带的RAM初始化工具很方便产生初始化文件. Xilinx的RAM初始化文件格式是coe, 在vivado中软件会将coe文件变 ...
- 写给技术lead的招聘指南
工作这么久,面试过的工程师不下两三百人.大部份招到的人都比靠谱当然也有失败的例子.把亲身经历总结如下: 1. 什么人一定不能招: 理解能力差: 对你提出的问题,答不对题,重复提问.面试官可以在面试当中 ...
- 消息中间件与RPC的区别
消息中间件和消息通信与RPC各自具有怎样的优势,如何互补消息中间件主要实现的是异步.弹性消息以及队列,弹性消息有时可以借助于外存从而一定程度上可以实现峰值缓存,有效均衡服务器端压力,同时消息可以进行一 ...
- MongoDB最简单的入门教程之三 使用Java代码往MongoDB里插入数据
前两篇教程我们介绍了如何搭建MongoDB的本地环境: MongoDB最简单的入门教程之一 环境搭建 以及如何用nodejs读取MongoDB里的记录: MongoDB最简单的入门教程之二 使用nod ...
- 十分钟搭建App主流框架
搭建主流框架界面 0.达成效果 Snip20150904_5.png 我们玩iPhone应用的时候,有没发现大部分的应用都是上图差不多的结构,下面的TabBar控制器可以切换子控制器,上面又有Navi ...
- DFS、BFS和Backtracking模板
区别与联系 区别 DFS多用于连通性问题因为其运行思想与人脑的思维很相似,故解决连通性问题更自然,采用递归,编写简便(但我个人不这样觉得...) DFS的常数时间开销会较少.所以对于一些能用DFS就能 ...
- 课外作业(建立double类型的小数,按照四舍五入保留2位小数)
举例:
- 实训day02 python
一.数据类型 列表: 定义:在[]内,可以存放多个任意类型的值,并以逗号隔开: 一般用于存放学生的爱好,课堂的周期等. 定义一个学生列表,可存放多个学生 students = ['A','B','C' ...
- js数字转金额,ajax调用接口,后台返回html(完整页面),打开新窗口并写入html
一.转换成金额形式 function toMoney(num){ if(num){ if(isNaN(num)) { alert("金额中含有不能识别的字符"); return; ...
- fork 和 exec
https://blog.csdn.net/disadministrator/article/details/39347333 进程创建方法:fork.exec.clone,父进程等待子进程结束是用w ...