【luogu P3376】 网络最大流 题解

一点小小的吐槽

我愿称luogu的这道网络流模板题为最强模板题

原题链接

第一次发现当前弧优化还有这些奇奇怪怪的小细节

那个flow==0的判断位置查了我两个小时

最气的是查出来后还贼有道理 还喷不了它

代码库

dinic

本人使用dinic 由于网络上题解众多 此处直接放出代码 并附上在连交10发中发现的小细节

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
#define REG register
#define rep(i,a,b) for(REG int i=a;i<=b;i++)
inline char getc(){
    static char buf[1<<14],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<14,stdin),p1==p2)?EOF:*p1++;
}
inline int scan(){
    REG int x=0; REG char ch=0;
    while(ch<48) ch=getc();
    while(ch>=48) x=x*10+ch-48,ch=getc();
    return x;
}
//我一开始开的是5002 后来意识到下标是从2开始的 于是开大了一点 影响未知
const int N=202,M=5005;
const ll INF=1e18;
//这玩意我一开始没开long long 
//虽然每一条边的容量都 <2147483648 但是到汇点的流量可以是多条边进去 所以是会超的
//不开long long见祖宗
int head[N],nex[M<<1],to[M<<1]; ll wei[M<<1];
inline void addEdge(int u,int v,int w){
    static int cc=1; //由2起的标号 便于取反 一开始忘了wa了1发
    nex[++cc]=head[u]; to[cc]=v; wei[cc]=w; head[u]=cc;
}
int n,m,s,t,d[N],cur[N],Q[N],l,r;
inline bool bfs(){
    //rep(i,1,n) if(cur[i]==head[i]) printf("???\n");
    rep(i,1,n) cur[i]=d[i]=0;
    l=1,r=0; Q[++r]=s; d[s]=1;
    REG int u;
    while(l<=r){
        u=Q[l++]; cur[u]=head[u];
        for(REG int i=head[u];i;i=nex[i]){
            if(d[to[i]]||!wei[i]) continue;
            Q[++r]=to[i]; d[to[i]]=d[u]+1;
        }
    }
    return d[t];
}
inline ll dfs(int u,ll flow){
    if(u==t) return flow;
    //把temp开在for外面会快一点(不过这一点很显然就是了)
    REG ll rest=0,temp;
    //经测试register的引用完全没有问题 至于是否未知的bug我就不懂了
    for(REG int &i=cur[u];i;i=nex[i]){
    	//若此处写成 for(REG int &i=cur[u];i&&flow;i=nex[i]) 然后后面不break 就会T
        if(d[to[i]]==d[u]+1&&wei[i]){
            temp=dfs(to[i],min(flow,wei[i]));
            rest+=temp; flow-=temp;
            wei[i]-=temp; wei[i^1]+=temp;
        }
        //在此处break与放在for函数的区别在于如果此边还有残量 这一边就不会被当前弧优化跳过
        if(!flow) break;
    }
    //此处有个剪枝 虽然没有这个也会因为当前弧到底而退出 不过加上还是快了点
    if(rest==0) d[u]=0;
    return rest;
}
int main(){
    //freopen("P3376_9.in","r",stdin);
    n=scan(),m=scan(),s=scan(),t=scan();
    REG int u,v,w; 
    while(m--){
        u=scan(); v=scan(); w=scan();
        addEdge(u,v,w); addEdge(v,u,0);
    }
    REG ll res=0;
    while(bfs()) res+=dfs(s,INF);
    printf("%lld\n",res);
    return 0;
}

END

posted @ 2020-10-13 00:20  喵乖乖喵  阅读(183)  评论(0编辑  收藏  举报

膜拜众神

网安院技术部     ZZY大师     Xinyang 大佬     Wjyyy