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 ...
随机推荐
- Android学习笔记(十八) Socket
Socket在计算机网络中的概念是指套接字,包含IP地址和端口号.在Java编程中Socket是一个类,用来实现数据传输(同样可以理解为“套接字”).传输的协议包括UDP和TCP,前者为不可靠的无连接 ...
- The Performance Manifesto
Manifesto For Performance Testing And Engineering We choose to support others in their quest for bet ...
- qt qtableview 样式设置
转载请注明出处:http://www.cnblogs.com/dachen408/p/7531159.html 1.设置tableview的列宽时,必须先setModel再setColumnWidge ...
- HDU 4465 Candy (数学期望)
题意:有两个盒子各有n个糖(n<=2*105),每天随机选1个(概率分别为p,1-p),然后吃掉一颗糖.直到有一天打开盒子一看,这个盒子没有糖了.输入n,p,求此时另一个盒子里糖的个数的数学期望 ...
- COGS 495. 窗口
★☆ 输入文件:window.in 输出文件:window.out 简单对比时间限制:2 s 内存限制:256 MB [问题描述] 给你一个长度为N的数组,一个长为K的滑动的窗体从最左 ...
- 螺旋数字的python实现
螺旋数字的算法简单实现. 示例 5 01 02 03 04 05 16 17 18 19 06 15 24 25 20 07 14 23 22 21 08 13 12 11 10 09 通过观察,外部 ...
- Windows下使用python库 curses遇到错误消息的解决方案
在Windows系统下执行python应用时,有时会遇到错误信息: ModuleNotFoundError: No module named '_curses'. 然而查看Windows系统里pyth ...
- mysqldump 使用详解
基本的使用方法总结: 1 导出所有库 系统命令行 mysqldump -uusername -ppassword --all-databases > all.sql 2 导入所有库 mysql ...
- vue 高度 动态更新计算 calcHeight watch $route
vue 高度 动态更新计算 calcHeight () { // this.tableHeight = window.innerHeight - 210 } }, mounted () { // co ...
- rfcn讲解博客
http://www.cnblogs.com/lillylin/p/6277094.html ROI pooling操作的输入(对于C+1个类)是k^2*(C+1)*W' *H'(W'和H'是ROI的 ...