zoukankan      html  css  js  c++  java
  • 【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("???
    ");
        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
    ",res);
        return 0;
    }
    

    END

  • 相关阅读:
    因为数据库无法大写循环所有要使用shell
    mysql动态扩容调研
    MySQL扩容
    数据库死锁及解决死锁问题
    SQL数据库常见故障及解决方法
    通过Ajax方式上传文件(input file),使用FormData进行Ajax请求
    Ajax方式上传文件
    高并发解决方案--负载均衡
    对TCP/IP协议的深入浅出总结
    常用的php开发工具有哪些?
  • 原文地址:https://www.cnblogs.com/Qing-LKY/p/luoguP3376-solution.html
Copyright © 2011-2022 走看看