Dinic全TLE求助

P3376 【模板】网络最大流

快斗游鹿 @ 2023-01-23 22:37:40

RT,本地测没问题,交上去全 TLE。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=20500;
struct edge{
    int to,nxt,w;
}e[N*2];
int n,m,s,t,cnt=1,head[N];
int dep[N],flag[N],ans;//dep深度,flag是否在队列中 
int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void add(int u,int v,int w){
    e[++cnt].to=v;
    e[cnt].nxt=head[u];
    e[cnt].w=w;
    head[u]=cnt;
}
bool bfs(){//分层 
    memset(dep,0,sizeof(dep));
    memset(flag,0,sizeof(flag));
    queue<int>q;
    dep[s]=1;
    q.push(s);
    while(!q.empty()){
        int u=q.front();q.pop();
        flag[u]=0;
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].to,w=e[i].w;
            if(!dep[v]&&w){
                dep[v]=dep[u]+1;
                if(!flag[v]){
                    q.push(v);flag[v]=1;
                }
            }
        }
    }
    if(dep[t])return 1;
    return 0;
}
int dfs(int u,int flow){//找增广路 
    int rlow=0;
    if(u==t)return flow;
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].to,w=e[i].w;
        if(w&&dep[v]==dep[u]+1){
            if(rlow=dfs(v,min(flow,w))){
                e[i].w-=rlow;
                e[i^1].w+=rlow;
                return rlow;
            }
        }
    }
}
void Dinic(){
    int lowflow;
    while(bfs()){
        while(lowflow=dfs(s,1145141919810))ans+=lowflow;
    }
}
signed main(){
    n=read();m=read();s=read();t=read();
    for(int i=1;i<=m;i++){
        int u,v,w;u=read();v=read();w=read();
        add(u,v,w);add(v,u,0);//正向边&反向边 
    }
    Dinic();
    printf("%lld",ans);
    return 0;
}

by bamboo12345 @ 2023-01-23 22:50:30

@快斗游鹿 我只知道你应该写的是EK


by bamboo12345 @ 2023-01-23 22:51:48

@快斗游鹿 会不会你dfs没有推出去流然后没有返回值炸了?


by TheSky233 @ 2023-01-23 23:10:48

@bamboo123 这就是 Dinic 啊


by TheSky233 @ 2023-01-23 23:13:01

@快斗游鹿 问题大概是你 depflag 数组开太大了然后 memset 导致的 TLE


by TheSky233 @ 2023-01-23 23:15:37

可以改成 memset(dep, 0, (n + 5) * sizeof(dep[0])),节省时间


by bamboo12345 @ 2023-01-24 08:40:10

@TheSky233 不是吧,dinic是同时找多条增广路吧,这个只找了1条


by bamboo12345 @ 2023-01-24 08:59:30

@快斗游鹿 就其实很无语dfs中加上return rlow 就可以只T一个点了 @TheSky233


by TheSky233 @ 2023-01-24 10:04:03

@bamboo123

多路增广是 dinic 的一种优化吧

其实在里面加上炸点就 A 了

int dfs(int u,int flow){//找增广路 
    int rlow=0;
    if(u==t)return flow;
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].to,w=e[i].w;
        if(w&&dep[v]==dep[u]+1){
            if(rlow=dfs(v,min(flow,w))){
                e[i].w-=rlow;
                e[i^1].w+=rlow;
                return rlow;
            }
        }
    }
    if(!rlow) dep[u]=-2;
    return 0;
}

by TheSky233 @ 2023-01-24 10:06:41

但是更推荐 bamboo123 说的多路增广,如果可以的话再增加一个当前弧优化(?

ll dfs(int now, ll flow){
    ll tot = 0, f = 0;
    if(now == t || flow == 0) return flow;
    for(int i = cur[now]; i; i = G[i].next){
        cur[now] = i;
        int t = G[i].to;
        if(G[i].w && dep[t] == dep[now] + 1){
            if(f = dfs(t, min(flow, G[i].w))){
                G[i].w -= f;
                G[i ^ 1].w += f;
                tot += f;
                flow -= f;
                if(flow == 0) break;
            }
        }
    }
    return tot;
}

by 快斗游鹿 @ 2023-01-24 10:07:43

@bamboo123 @TheSky233 明白了,感谢!


| 下一页