MnZn求助Dinic当前弧优化

P3376 【模板】网络最大流

wgyhm @ 2021-01-05 20:04:27

这是我没有加当前弧优化的代码,耗时稳定在 100ms 以内:

#include<bits/stdc++.h>
#define maxn 1005
#define rg register
#define int long long
using namespace std;
inline void read(int &x){
    int f=1;x=0;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
    x*=f;
}//快读
int now[maxn],h[maxn],deep[maxn],head,s,t,n,m;
struct yyy{
    int to,z,w;
    inline void add(int x,int y,int W){
        to=y;z=h[x];h[x]=head;w=W;
    }
}a[100005];
queue<int>q;
inline bool bfs(void){
    rg int i,x;
    memset(deep,0,sizeof(deep));
    q.push(s);deep[s]=1;
    while (!q.empty()){
        x=q.front();q.pop();
        for (i=h[x];i;i=a[i].z)
            if (a[i].w&&!deep[a[i].to]){
                deep[a[i].to]=deep[x]+1;
                q.push(a[i].to);
            }
   }
   return deep[t];
}
inline int dfs(int x,int in){
    rg int i,rest=in,sum;
    if (x==t) return in;
    for (i=h[x];i&&rest;i=a[i].z)
         if (deep[a[i].to]==deep[x]+1&&a[i].w){
             sum=dfs(a[i].to,min(rest,a[i].w));
             if (!sum) deep[a[i].to]=0;
             a[i].w-=sum;a[i^1].w+=sum;rest-=sum;
         }
    return in-rest;
}
inline int Dinic(void){
    int ans=0;
    while (bfs()) ans+=dfs(s,1e9);
    return ans;
}
signed main(){
    rg int i,x,y,z;head=1;
    read(n);read(m);read(s);read(t);
    while (m--){
        read(x);read(y);read(z);
        a[++head].add(x,y,z);
        a[++head].add(y,x,0);
    }
    printf("%lld",Dinic());
    return 0;
}

这是加了当前弧优化,照着《算法竞赛进阶指南》上改的,但是加了以后时间在 900~1000ms 不等。

#include<bits/stdc++.h>
#define maxn 505
#define rg register
#define int long long
#define put() putchar('\n')
using namespace std;
inline void read(int &x){
    int f=1;x=0;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
    x*=f;
}//快读
int now[maxn],h[maxn],deep[maxn],head,s,t,n,m;
struct yyy{
    int to,z,w;
    inline void add(int x,int y,int W){
        to=y;z=h[x];h[x]=head;w=W;
    }
}a[100005];
queue<int>q;
inline bool bfs(void){
    memset(deep,0,sizeof(deep));
    rg int i,x;deep[s]=1;q.push(s);
    for (i=1;i<=n;i++) now[i]=h[i];
    while (!q.empty()){
        x=q.front();q.pop();
        for (i=h[x];i;i=a[i].z)
            if (!deep[a[i].to]&&a[i].w){
                deep[a[i].to]=deep[x]+1;
                q.push(a[i].to);
            }
    }
    return deep[t];
}
inline int dfs(int x,int in){
    if (x==t||!in) return in;
    rg int rest=in,i,sum;
    for (i=now[x];i&&rest;i=a[i].z)
        if (a[i].w&&deep[a[i].to]==deep[x]+1){
            sum=dfs(a[i].to,min(rest,a[i].w));
            if (!sum) deep[a[i].to]=0;
            a[i].w-=sum;a[i^1].w+=sum;rest-=sum;
        }
    now[x]=a[i].z;//当前弧优化
    return in-rest;
}
inline int Dinic(void){
    rg int ans=0,in;
    while (bfs()) ans+=dfs(s,1e18);
    return ans;
}
signed main(){
    rg int i,x,y,z;head=1;
    read(n);read(m);read(s);read(t);
    while (m--){
        read(x);read(y);read(z);
        a[++head].add(x,y,z);
        a[++head].add(y,x,0);
    }
    printf("%lld",Dinic());
    return 0;
}

请问我的当前弧优化哪里写假了?

还是我加的就是一个假的当前弧优化?

或者说是数据无意就使我的代码这么慢?

调了一个月了,求大佬解答。


by BlankAo @ 2021-01-05 20:25:53

   for (i=now[x];i&&rest;i=a[i].z){
        now[x]=i;
        if (a[i].w&&deep[a[i].to]==deep[x]+1){
            sum=dfs(a[i].to,min(rest,a[i].w));
            if (!sum) deep[a[i].to]=0;
            a[i].w-=sum;a[i^1].w+=sum;rest-=sum;
        }
    }

by BlankAo @ 2021-01-05 20:27:05

外面的now[x]=a[i].z;就去掉


by BlankAo @ 2021-01-05 20:27:32

@违规用户名FkZyA0!2


by cbio @ 2021-01-05 20:28:11

考虑一种情况,当一条边流出将rest用尽的话,这样写会直接跳过它,而不是下次再尝试流出


by wgyhm @ 2021-01-05 20:30:54

@BlankAo 按照您的写法为什么就可以啊?我觉得是等价的,但是您的写法就是快很多。。。


by wgyhm @ 2021-01-05 20:33:27

@cbio 我理解了,谢谢


by wgyhm @ 2021-01-05 20:33:56

此贴终结,感谢上面两位大佬


by zimujun @ 2021-01-07 18:09:33

@违规用户名FkZyA0!2 蓝书上的当前弧优化是假的


by wgyhm @ 2021-01-07 18:31:15

@zimujunqwq az


|