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 最大流 裸题的更多相关文章

  1. hdu Flow Problem (最大流 裸题)

    最大流裸题,贴下模版 view code#include <iostream> #include <cstdio> #include <cstring> #incl ...

  2. POJ 1087 最大流裸题 + map

    A Plug for UNIX Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 15597   Accepted: 5308 ...

  3. HDU-3549 最大流模板题

    1.HDU-3549   Flow Problem 2.链接:http://acm.hdu.edu.cn/showproblem.php?pid=3549 3.总结:模板题,参考了 http://ww ...

  4. HDU 3376 &amp;&amp; 2686 方格取数 最大和 费用流裸题

    题意: 1.一个人从[1,1] ->[n,n] ->[1,1] 2.仅仅能走最短路 3.走过的点不能再走 问最大和. 对每一个点拆点限流为1就可以满足3. 费用流流量为2满足1 最大费用流 ...

  5. 紫书 习题 11-3 UVa 820 (最大流裸题)

    注意这道题是双向边, 然后直接套模板就ok了. #include<cstdio> #include<algorithm> #include<vector> #inc ...

  6. POJ 2195 Going Home 最小费用流 裸题

    给出一个n*m的图,其中m是人,H是房子,.是空地,满足人的个数等于房子数. 现在让每个人都选择一个房子住,每个人只能住一间,每一间只能住一个人. 每个人可以向4个方向移动,每移动一步需要1$,问所有 ...

  7. 【填坑】bzoj3224 splay裸题

    人生第一道splay不出所料是一道裸题,一道水题,一道2k代码都不到的题 #include <cstdio> ,n,p,q; ],c[][],size[],sp[]; void rot(i ...

  8. tarjan讲解(用codevs1332(tarjan的裸题)讲解)

    主要借助这道比较裸的题来讲一下tarjan这种算法 tarjan是一种求解有向图强连通分量的线性时间的算法.(用dfs来实现) 如果两个顶点可以相互通达,则称两个顶点强连通.如果有向图G的每两个顶点都 ...

  9. LCT裸题泛做

    ①洞穴勘测 bzoj2049 题意:由若干个操作,每次加入/删除两点间的一条边,询问某两点是否连通.保证任意时刻图都是一个森林.(两点之间至多只有一条路径) 这就是个link+cut+find roo ...

随机推荐

  1. Eric's并发用户数估算与Little定律的等价性

    在国内性能测试的领域有一篇几乎被奉为大牛之作的经典文章,一个名叫Eric Man Wong 于2004年发表了名为<Method for Estimating the Number of Con ...

  2. 项目中常用git命令操作指令(一般正常的话够用不够再看相关git命令)

    配置git1.首先在本地创建ssh key:ssh-keygen -t rsa -C "github上注册的邮箱" //(一路回车)2.进入c:/Users/xxxx_000/.s ...

  3. 在Github上删除一个项目

    最近在Github上浏览,不小心fork了一个项目.想删除,现在记录下来. 1.点击选择fork的项目,以gubai为例 2.进入后,点击Settings 3.进入页面后,点击Delete this ...

  4. css广告弹窗满屏跑

    window.onload=function(){ //广告滚动 var oneInner = $('#divid')[0]; //定时器 var a1a = setInterval(moves,10 ...

  5. Android(java)学习笔记179:多媒体之加载大图片到内存(Bitmap API)

    1. Bitmap (API使用) android里面的bitmap中,一个像素点需要4个byte去表示,这是因为android表示颜色是" argb ":其中 a 表示是透明度, ...

  6. windows常用bat脚本

    windows常用bat脚本 https://blog.csdn.net/longyan_csc/article/details/78737722 Windows_批处理+任务计划实现文件夹定时备份 ...

  7. QT_8_Qt中的事件处理_定时器事件_定时器类_事件分发器_事件过滤器_绘图事件_高级绘图事件_绘图设备_QFile 文件读写_QFileInfo文件信息

    Qt中的事件处理 1.1. 捕获QLabel中是鼠标事件 1.2. enterevent 鼠标进入 1.3. leaveevent 鼠标离开 1.4. 鼠标按下MyLabel::mousePressE ...

  8. 如何使用postman访问网站

    1.输入Request URL2.选择Request Method3.输入需要的Request Headers注意:一般token会在Headers中

  9. Elasticsearch document深度剖析

    1. 针对Elasticsearch并发冲突问题,ES内部是如何解决的? 1)ES内部是线程异步并发修改的,是基于_version版本号进行乐观锁并发控制的: 2)若后修改的先到了,那么修改后版本发生 ...

  10. bzoj 3555 企鹅QQ

    https://www.lydsy.com/JudgeOnline/problem.php?id=3555 枚举每一位字符,计算字符两侧的哈希值,然后进行比较,用map或排序记录出与其相同的字符串数量 ...