【Acm|网络流-EK算法】EK算法的思路:
基于贪心的思想,每次选取一条起点到终点的路径,毋庸置疑,这条路的流量就等于这条路径上的权值是最小值。将这条路的权值都减去流量,再将路径的反向边加上流量(这样可以就给贪心一次反悔的机会),无限循环以上步骤,到找不到任何一条起点到终点的路,最后所有的最小值加起来就是最大流了。
(这只是我对EK算法的总结,学习网络流还是去看别人的博客吧)
代码:
#include
#include
#include
#include
#define LL long long
#define Max 100005
const LL mod=1e9+7;
const LL LL_MAX=9223372036854775807;
using namespace std;
struct node
{
int v,next;
LL w;
}edge[Max];
//使用邻接表存边
int n,m;
int pre[Max],head[Max],rec[Max];
//pre保存路径,rec保存该点在邻接表中的位置,head邻接表的指针
LL flow[Max];
//记录最小值
int no;
queueq;
void init()
{
no=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v,LL c){
edge[no].v=v,edge[no].w=c;
edge[no].next=head[u],head[u]=no++;
edge[no].v=u;
edge[no].w=0;
edge[no].next=head[v],head[v]=no++;
}LL bfs(int st,int en)//寻找st-->en的路径
{
memset(pre,-1,sizeof(pre));
while(!q.empty())q.pop();
pre[st]=st,flow[st]=INT_MAX;
q.push(st);
while(!q.empty()){
int top=q.front();
q.pop();
int now=head[top];
while(now!=-1){
int t=edge[now].v;
if(pre[t]==-1 && edge[now].w>0){//该点没有被访问过,且权值不为0
flow[t]=min(flow[top],edge[now].w);
pre[t]=top;
rec[t]=now;
q.push(t);
}
now=edge[now].next;
}
if(pre[en]!=-1)
return flow[en];
}
return -1;
}
LL EK(int st,int en)
{
LL ans=0;
LL add;
while((add=bfs(st,en))!=-1){//走遍所有st-->en的路径
ans+=add;
int k=en;
// printf("%d\n",add);
while(k!=pre[k]){
edge[rec[k]].w-=add;
//权值减去最小值
edge[rec[k]^1].w+=add;
//反向边加上最小值
//printf("%d\n",k);
k=pre[k];
}
}
return ans;
}
int main()
{
int x,y;
LL c;
while(scanf("%d%d",&m,&n)==2){
init();
for(int i=0;
i
推荐阅读
- ACM|HDU 5322 Hope (CDQ分治+NTT)
- 牛客算法周周练15——A、B
- Codeforces Round #609 (Div. 2)——C. Long Beautiful Integer(思维)
- FZU - 2107题解
- ACM OJ 2036 多边形面积计算
- #|【牛客】牛客练习赛67-E-牛妹游历城市——位运算优化
- ACM|回文树(自动机)(练习和总结)
- acm|扩展欧几里德算法(附证明)
- ACM|[dsu] codeforces 375D. Tree and Queries
- ACM|codeforces 732-D. Exams (二分)