zoukankan      html  css  js  c++  java
  • 并不对劲的网络流

    网络流问题可以看成是从一个单位时间流量超级大的水龙头经过一些粗细不一的水管流向下水道的问题,一般情况下是要求合理分配流量,使得单位时间内流向下水道的水量最大。

     现在,水龙头开闸放水,假设自己是一个水分子。那么会怎么走呢?当然是找出一条能走到下水道的并且没有被流满的路,然后沿着这条路走到下水道就行了。网络流的增广路算法就是模拟这个过程,每次找出一条可以走到终点的路,把这条路流满,再找下一条路。注意不要忘记建反向弧,反向弧相当于反悔的机会。用水来比喻的话,就是一来一回两股水流,相当于没有,互相抵消了。

    ek算法就是每次bfs找出可行的路,把这条路流满,再找下一条,复杂度是o(点数*(边数^2)) 。

    dinic的原理和ek类似,但是它是每次一边bfs给图分层,然后dfs,只走dis[u]+1==dis[v]的边(保证不会原地绕圈),无路可走就再bfs一遍,直到原点走不到汇点,复杂度是o(边数*(点数^2),代码也不是很难写,所以大部分人都用这个。

    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #define maxn 10010
    #define maxm 100010
    using namespace std;
    int fl[maxm*2],v[maxm*2],w[maxm*2],nxt[maxm*2],fir[maxn];
    int n,m,kk,cnt,dis[maxn],dep[maxn],inf,s,t,maxflow;
    bool vis[maxn];
    int read()
    {
        int x=0,f=1;
        char ch=getchar();
        while(isdigit(ch)==0 && ch!='-')ch=getchar();
        if(ch=='-')f=-1,ch=getchar();
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    void addedge(int u1,int v1,int fl1)
    {
        fl[cnt]=fl1,v[cnt]=v1,nxt[cnt]=fir[u1],fir[u1]=cnt;cnt++;
        fl[cnt]=0,v[cnt]=u1,nxt[cnt]=fir[v1],fir[v1]=cnt;cnt++;
    }
    int bfs()
    {
        memset(dep,-1,sizeof(dep));
        queue<int>q;
        dep[s]=0;
        q.push(s);
        while(!q.empty())
        {
            int u=q.front();q.pop();
            for(int k=fir[u];k!=-1;k=nxt[k])
            {
                int vv=v[k];
                if(fl[k]>0)
                {
                    if(dep[vv]==-1 || dep[vv]>dep[u]+1)
                    {
                        dep[vv]=dep[u]+1;
                        q.push(vv);
                    }
                    
                }
            }
        }
        return dep[t];
    }
    int dfs(int u,int nowflow)
    {
        int flow=0,tmp;
        if(u==t || nowflow==0)return nowflow;
        for(int k=fir[u];k!=-1;k=nxt[k])
        {
            int i=v[k];
            if(fl[k]>0 && dep[i]==dep[u]+1 && (tmp=dfs(i,min(nowflow,fl[k])))>0)
            {
                flow+=tmp;
                fl[k]-=tmp;
                fl[k^1]+=tmp;
                nowflow-=tmp;
            }
        }
        return flow;
    }
    int main()
    {
        memset(fir,-1,sizeof(fir));
        n=read(),m=read(),s=read(),t=read();
        for(int i=1;i<=m;i++)
        {
            int u1=read(),v1=read(),fl1=read();
            addedge(u1,v1,fl1);
        }
        while(bfs()!=-1)
        {
            maxflow+=dfs(s,0x7fffffff);
        }
        cout<<maxflow;
        return 0;
    }
    并不对劲的网络流

    事实上,某些神奇优化+卡常能使它跑的极快。

    #include <bits/stdc++.h>
    #define maxn 1000010
    #define maxm 8000010
    #define LL long long 
    #define re register 
    using namespace std;
    struct maxflow
    {
        int v[maxm*2],nxt[maxm*2],fir[maxn],tfir[maxn];
        int n,m,kk,cnt,dis[maxn],dep[maxn],inf[10],s,t,maxflow;
        LL fl[maxm*2];
        inline LL llread()
        {
            LL x=0,f=1;
            char ch=getchar();
            while(isdigit(ch)==0 && ch!='-')ch=getchar();
            if(ch=='-')f=-1,ch=getchar();
            while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
            return x*f;
        }
        inline int read()
        {
            int x=0,f=1;
            char ch=getchar();
            while(isdigit(ch)==0 && ch!='-')ch=getchar();
            if(ch=='-')f=-1,ch=getchar();
            while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
            return x*f;
        }
        inline void write(int x)
        {
            int f=0;char ch[20];
            if(!x){puts("0");return;}
            if(x<0){putchar('-');x=-x;}
            while(x)ch[++f]=x%10+'0',x/=10;
            while(f)putchar(ch[f--]);
            putchar('
    ');
        }
        inline void addedge(int u1,int v1,LL fl1)
        {
            fl[cnt]=fl1,v[cnt]=v1,nxt[cnt]=fir[u1],fir[u1]=cnt;cnt++;
            fl[cnt]=0,v[cnt]=u1,nxt[cnt]=fir[v1],fir[v1]=cnt;cnt++;
        }
        bool bfs()
        {
            for(int i=1;i<=n;i++)
                dep[i]=-1;
        	queue<int >q;
            dep[t]=0;
            q.push(t);
            while(!q.empty())
            {
                int u=q.front();q.pop();
                for(re int k=fir[u];k!=-1;k=nxt[k])
                {
                	int vv=v[k];
                	if(fl[k^1]>0)
                	{
                        if(dep[vv]==-1)
                        {
                            dep[vv]=dep[u]+1;
                            if(vv==s)return 1;
                            q.push(vv);
                        }
                		
                    }
                }
            }
            return 0;
        }
        int dfs(int u,LL nowflow)
        {
            LL flow=0,tmp;
            if(u==t || !nowflow)return nowflow;
            for(re int &k=tfir[u];k!=-1;k=nxt[k])
            {
            	int i=v[k];
                if(!fl[k])continue;
                if(dep[u]==dep[i]+1 && (tmp=dfs(i,min(nowflow,fl[k])))>0)
                {
                    flow+=tmp;
                    fl[k]-=tmp;
                    fl[k^1]+=tmp;
                    nowflow-=tmp;
                }
            	if(!nowflow)break;
            }
            return flow;
        }
        void work()
        {
            memset(fir,-1,sizeof(fir));
            memset(inf,0x7f,sizeof(inf));
            n=read(),m=read(),s=read(),t=read();
            for(re int i=1;i<=m;i++)
            {
            	LL u1=read(),v1=read(),fl1=llread();
            	addedge(u1,v1,fl1);
            }
            while(bfs())
            {
            	for(re int i=1;i<=n;i++)
            	    tfir[i]=fir[i];
                maxflow+=dfs(s,inf[0]);
            }
            write(maxflow);
        }
    } t;
    
    int main()
    {
        t.work();
        return 0;
    }
    

      

  • 相关阅读:
    同一个类生成的对象去重
    关于公众号JavaTokings侵权声明
    消息中间件ActiveMQ使用详解
    重定向和转发的分析与理解
    Oracle SqlPlus导出查询结果
    Sql查询一个列对应多个列
    Jsp标签字典开发_基于Spring+Hibernate
    Oracle数据库导入导出简单备份
    JAVA WEB接口开发简述
    NTKO在线office控件使用实例
  • 原文地址:https://www.cnblogs.com/xzyf/p/8000959.html
Copyright © 2011-2022 走看看