今天上午我仿佛知道了什么叫做网络流,这里推荐一篇博客,大家入门网络流的可以看一下这篇博客,保证一看就懂!

博客链接:

网络流入门

这里有一篇经过我改过的EK带注释代码(博客里也有一样的,只是加了一些注释),大家可以看一下:

//codevs 1993
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int INF=0x7ffffff; queue <int> q;
int n,m,x,y,s,t,g[201][201],pre[201],flow[201],maxflow;
//g邻接矩阵存图,pre增广路径中每个点的前驱,flow源点到这个点的流量 (就是増广路(min))! inline int bfs(int s,int t)
{
while (!q.empty()) q.pop();//清空!
for (int i=1; i<=n; i++) pre[i]=-1;//清空!!!
pre[s]=0;
q.push(s);
flow[s]=INF;
while (!q.empty())
{
int x=q.front();
q.pop();
if (x==t) break;
for (int i=1; i<=n; i++)
//EK一次只找一个增广路 ,这句话非常的重要啊!!!!!important! very important! very very important!!!
//不认真看这句话,不要怪下面自己看不懂!
if (g[x][i]>0 && pre[i]==-1)//如果当时x到i点有容量,并且i点还没有找到前驱
{
pre[i]=x;
flow[i]=min(flow[x],g[x][i]);//是不是觉得有一点像SPFA ??? 找最小的増广路
q.push(i);
}
}
if (pre[t]==-1) return -1;//死啦!
else return flow[t];
} //increase为增广的流量
void EK(int s,int t)
{
int increase=0;
while ((increase=bfs(s,t))!=-1)//这里的括号加错了!Tle
{//迭代
int k=t;//k等于终点
while (k!=s)//当k不为起点时
{
int last=pre[k];//从后往前找路径
g[last][k]-=increase;//正着走残量网络要减去增广量
g[k][last]+=increase;//反之,反着走要加上增广量
k=last;
}
maxflow+=increase;//增加増广路
}
} int main()
{
scanf("%d%d",&m,&n);//m是挖了几条沟,n是有几条汇点 ,最后一个点n也是小溪的编号
for (int i=1; i<=m; i++)
{
int z;
scanf("%d%d%d",&x,&y,&z);
g[x][y]+=z;//此处不可直接输入,要+= ,为什么???????????????important
}
EK(1,n);
printf("%d",maxflow);
return 0;
}

下面大家就会发现一个问题,用邻接矩阵存储,是不是也太费空间了,要是题目让你跑一个有10000个点的网络流岂不凉凉!!!

下面就要献上我们改装过的EK算法!(说白了就是Dinic)

#include<bits/stdc++.h>
using namespace std;
struct listx{
int to,next=0,f;
}edge[200005];
int cnt=0,n,m,s,t;
int head[10005];
int depth[10005];
void update(int num,int flow)
{
edge[num].f-=flow;
edge[num+1].f+=flow;
}
void addedge(int u,int v,int w)
{
cnt++;
edge[cnt].next=head[u];
edge[cnt].to=v;
edge[cnt].f=w;
head[u]=cnt;
}
bool bfs()
{
memset(depth,0,sizeof(depth));
queue<int>que;
while(!que.empty())
{
que.pop();
}
que.push(s);
depth[s]=1;
while(!que.empty())
{
int cur=que.front();
que.pop();
if(cur==t)
break;
for(int i=head[cur];i!=0;i=edge[i].next)
{
listx temp=edge[i];
if(depth[temp.to]==0&&temp.f>0)
{
depth[temp.to]=depth[cur]+1;
que.push(temp.to);
}
}
}
if(depth[t]==0)
return false;
return true;
}
int dfs(int u,int flow)
{
if(u==t)
return flow;
for(int i=head[u];i!=0;i=edge[i].next)
{
listx temp=edge[i];
if(depth[u]+1==depth[temp.to]&&temp.f>0)
{
flow=flow<temp.f?flow:temp.f;
int newx=dfs(temp.to,flow);
if(newx>0)
{
update(i,newx);
return newx;
}
}
}
return 0;
}
int main()
{
int ans=0;
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=1;i<=m;i++)
{
int a1,b1,c1;
scanf("%d%d%d",&a1,&b1,&c1);
addedge(a1,b1,c1);
addedge(b1,a1,0);
}
while(bfs())
{
int k;
while(k=dfs(s,10000000))
{
ans+=k;
}
}
printf("%d",ans);
return 0;
}

最新文章

  1. URL传递中文字符,特殊危险字符的解决方案(仅供参考)urldecode、base64_encode
  2. google 版本号49之后chrome的跨域设置
  3. Show Roles Assigned to a Specific User
  4. css tricks
  5. HDOJ 4974 A simple water problem
  6. @media max-width 与jquery宽度取值的差异
  7. TensorFlow 处理图片
  8. 更多细节的理解RSA算法
  9. 浏览器与Node的事件循环(Event Loop)有何区别?
  10. 宝塔linux面版安装网站环境 自动化
  11. Java内存空间的分配及回收
  12. JS — 数组去重(4种方法)
  13. vue初始化数据加载
  14. apicloud管理
  15. spring-session实现分布式集群session的共享(转)
  16. 输入一个URL到页面呈现其中发生的过程-------http过程详解
  17. Luogu1309 瑞士轮(分治,归并排序)
  18. 深入理解JSON
  19. RHCE7 管理II-4计划将来的Linux任务
  20. Html中meta标签详解--以前经常忽略的

热门文章

  1. Linux 连接 Xshell 及网络配置
  2. Thrift笔记(五)--Thrift server源码分析
  3. Python爬虫《http和https协议》
  4. JavaScript Callback 回调函数
  5. select @@identity用法
  6. 《ArcGIS Runtime SDK for Android开发笔记》——离在线一体化技术:概述
  7. Eclipse 各版本名称的由来
  8. To find names containing exactly five characters, use “^”and “$”to match the beginning and end of the name, and five instances of “.”in between: mysql
  9. 新发布 | Azure镜像市场正式上线
  10. supervisor运行virtualenv环境下的nagios-api