zoukankan      html  css  js  c++  java
  • 网络流

    今天开始学网络流...

    首先是bfs找通流的EK算法..

    #include<bits/stdc++.h>
    using namespace std;
    const int N=10010,M=100010,qwq=1<<30;
    int link[N],tot=1,n,m,s,t,maxflow,vis[N],id,incf[N],pre[N];
    struct edge{int y,v,next;}a[M<<1]; 
    inline int read()
    {
        int x=0,ff=1;
        char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*ff;
    }
    inline void add(int x,int y,int v)
    {
        a[++tot].y=y;
        a[tot].v=v;
        a[tot].next=link[x];
        link[x]=tot;
    }
    inline bool bfs()
    {
        queue<int>q;q.push(s);
        id++;vis[s]=id;//标记源点 
        incf[s]=qwq;//初始化流量 
        while(q.size())
        {
            int x=q.front();q.pop();
            for(int i=link[x];i;i=a[i].next)
            {
                if(a[i].v)//如果当前的边有剩余流量 
                {
                    int y=a[i].y;
                    if(vis[y]==id) continue;//若已标记过,则退出. 
                    incf[y]=min(incf[x],a[i].v);//更新最小剩余流量 
                    pre[y]=i;//记录点的前驱(记录的是边) 
                    q.push(y);vis[y]=id;//标记这个点 
                    if(y==t) return true;//如果到达汇点,则返回true 
                }
            }
        }
        return false;
    }
    inline void update()
    {
        int x=t;//从汇点出发. 
        while(x!=s)
        {
            int i=pre[x];//找到来时的边 
            a[i].v-=incf[t];//这条边剩余容量减少 
            a[i^1].v+=incf[t];//边的反向边剩余容量增加 
            x=a[i^1].y;//退回到上一个点 
        }
        maxflow+=incf[t];//最大流量更新. 
    } 
    int main()
    {
        freopen("1.in","r",stdin); 
        n=read(),m=read(),s=read(),t=read();
        for(int i=1;i<=m;++i)
        {
            int x=read(),y=read(),v=read();
            add(x,y,v);add(y,x,0);//反向边的边权为0 
        }
        while(bfs()) update();
        printf("%d",maxflow);
        return 0;
    }
    View Code
     

    之后就是优化的dfs剪枝找通流dinic算法(现在还是好迷得.....):

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=10010,M=100010,qwq=1<<30;
    int n,m,s,t,link[N],d[N],tot=1;
    ll maxflow;
    struct edge{int y,v,next;}a[M<<1];
    inline int read()
    {
        int x=0,ff=1;
        char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*ff;
    }
    inline void add(int x,int y,int v)
    {
        a[++tot].y=y;
        a[tot].v=v;
        a[tot].next=link[x];
        link[x]=tot;
    }
    inline bool bfs()
    {
        queue<int>q;q.push(s);
        memset(d,0,sizeof(d));
        d[s]=1;//初始化s的深度. 
        while(!q.empty())
        {
            int x=q.front();q.pop();
            for(int i=link[x];i;i=a[i].next)
            {
                int y=a[i].y;
                if(a[i].v&&!d[y])//如果当前边有剩余流量且还没有便利过 
                {
                    q.push(y);
                    d[y]=d[x]+1;
                    if(y==t) return true;//这里忽略了其他深度比t大的点,但其实 
                }//已经构成了从s到t的残余网络. 
            }
        }
        return false;
    }
    inline int dinic(int x,int flow)
    {
        if(x==t) return flow;
        int rest=flow,k;//rest表示flow与k的差值. 
        for(int i=link[x];i&&rest;i=a[i].next)//如果rest为0直接退出. 
        {
            int y=a[i].y;
            if(a[i].v&&d[y]==d[x]+1)
            {
                k=dinic(y,min(rest,a[i].v));//k表示当前找到的最小流量. 
                if(!k) d[y]=0;//如果k为0,直接将这个点删掉 
                a[i].v-=k;
                a[i^1].v+=k;//更新边权 
                rest-=k;//rest表示flow与k的差值 
             }
        }
        return flow-rest;
    }
    int main()
    {
        freopen("1.in","r",stdin);
        n=read();m=read();s=read();t=read();
        for(int i=1;i<=m;++i)
        {
            int x=read(),y=read(),v=read();
            add(x,y,v);add(y,x,0);
        }
        int flow=0;
        while(bfs())//构建残余网络 
            while(flow=dinic(s,qwq)) maxflow+=flow;//累加剩余流量. 
        printf("%lld",maxflow);
        return 0; 
    }
    View Code
    
    
  • 相关阅读:
    大数据概述
    语法分析-代码
    语法分析-C语言程序
    Hadoop综合大作业
    hive基本操作与应用
    理解MapReduce计算构架
    熟悉HBase基本操作
    爬虫大作业
    熟悉常用的HDFS操作
    数据结构化与保存
  • 原文地址:https://www.cnblogs.com/gcfer/p/12235873.html
Copyright © 2011-2022 走看看