zoukankan      html  css  js  c++  java
  • 【模板】【网络流】【网络最大流】FF,bfs,dinic

    之前写好的网络流笔记没有保存,不见了,懒得弄了,直接贴代码了

    什么时候闲了再回来搞吧

    //科学计数法:2e9 
    //1dfs 
    //其实我是有一点拿网络流练dfs的意思的 
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm> 
    #include<cstring>
    using namespace std;
    const int inf=2e9; 
    int n,m,s,ed;//明确了以后用ed表示终点 
    const int N=10003,M=100003;//这里主要看N的大小,N不大就用邻接矩阵,N太大N^2就会MLE,用邻接表
    int head[N],tot=1; 
    struct node
    {
        int v,w,nx;
    }e[M<<1];//双向边
    void add(int u,int v,int w)
    {
        e[++tot].v =v,e[tot].w =w,e[tot].nx =head[u],head[u]=tot;
        e[++tot].v =u,e[tot].w =0,e[tot].nx =head[v],head[v]=tot;//这里把反向边的值设置成0,防止反向走边 
    }
    
    bool vis[N];
    int dfs(int x,int flow)
    {
        for(int i=head[x];i;i=e[i].nx )
        {
            int v=e[i].v ,w=e[i].w ;
            
            if(vis[v] || w<=0) continue;
            
            vis[v]=true;
            int t=min(flow,w),tt;
            if(v==ed) 
            {
                e[i].w -=t,e[i^1].w +=t;
                return t;
            }
            else if( (tt=dfs(v,t))>0  )//夭寿咯 
            {
                e[i].w -=tt;
                e[i^1].w +=tt;
                return tt;
            }
        }
        return 0;
    }
    
    int ans;
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&s,&ed);
        int u,v,w;
        while(m--)
            scanf("%d%d%d",&u,&v,&w),add(u,v,w);
        //练习dfs剪枝啦~~ 
        int ttt=0;
        while((memset(vis,false,sizeof(vis)) &&(vis[s]=true) ) && ( ttt=dfs(s,inf))>0)//夭寿咯 
            ans+=ttt; 
        printf("%d",ans);
        
        return 0;
    } 
    //FF算法 
    //1    dfs 1.09s 
    //2    bfs 330s
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm> 
    #include<cstring>
    #include<queue>
    using namespace std;
    const int inf=2e9; 
    int n,m,s,ed;//明确了以后用ed表示终点 
    const int N=10003,M=100003;//这里主要看N的大小,N不大就用邻接矩阵,N太大N^2就会MLE,用邻接表
    int head[N],tot=1; 
    struct node
    {
        int v,w,nx;
    }e[M<<1];//双向边
    void add(int u,int v,int w)
    {
        e[++tot].v =v,e[tot].w =w,e[tot].nx =head[u],head[u]=tot;
        e[++tot].v =u,e[tot].w =0,e[tot].nx =head[v],head[v]=tot;//这里把反向边的值设置成0,防止反向走边 
    }
    
    int pre[N];//作用更大的vis标记
    int flow[N];//没有dfs一整条路径来记,每个点的flow只能自己记着 
    int ans;
    void bfs()
    {
        queue <int> q;
        while(1)
        {
            memset(pre,0,sizeof(pre));
            memset(flow,0,sizeof(flow));//清空 
            //找边 
            pre[s]=-1,flow[s]=inf;//这里的pre不能是0,否则会被遍历到 //flow依旧设成无限大 
            while(!q.empty() ) q.pop() ;
            q.push(s); 
            while(!flow[ed] && !q.empty() )
            {
                int u=q.front() ;q.pop() ;
                for(int i=head[u];i;i=e[i].nx )
                {
                    int v=e[i].v ;
                    if(!flow[v] && e[i].w >0)
                        pre[v]=i,flow[v]=min(flow[u],e[i].w ),q.push(v); 
                }
            } 
            if(!flow[ed]) break;
            //没有增广路就退出
            ans+=flow[ed];
            int pos=pre[ed],tt=flow[ed];
            while( pos >0)//注意!!!夭寿咯 
            {
                e[pos].w -=tt;
                e[pos^1].w +=tt;
                pos=pre[e[pos^1].v ];
            }
        }  
        printf("%d",ans);
    }
    
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&s,&ed);
        int u,v,w;
        while(m--)
            scanf("%d%d%d",&u,&v,&w),add(u,v,w);
        //bfs加速搜索啦~~ 
        bfs();
        
        return 0;
    } 
    //3dinic 154ms
    #include<cstdio>
    #include<cstdlib>
    #include<queue>
    #include<cstring>
    using namespace std;
    int n,m,s,ed;
    const int N=10003,M=100003,inf=2e9;
    struct node
    { int v,w,nx; }e[M<<1];
    int tot=1,head[N];
    void add(int u,int v,int w)
    { e[++tot].v =v,e[tot].w =w,e[tot].nx =head[u],head[u]=tot; }
    
    int cur[N],dep[N],depth;
    int bfs()
    {
        memset(dep,0,sizeof(dep));
        dep[s]=1;
        queue <int> q;
        q.push(s);
         
        while(!dep[ed] && !q.empty() )
        {
            int u=q.front() ;q.pop() ;
            for(int i=head[u];i;i=e[i].nx )
            {
                int v=e[i].v ;
                if(!dep[v] && e[i].w >0)
                    dep[v]=dep[u]+1,q.push(v); 
            }
        }
        return depth=dep[ed];
    }
    int dfs(int x,int flow)
    {
        int ans=0;
        if(x==ed) return flow;
        if(!dep[x] || dep[x]>depth) return 0;
        for(int i=head[x];i;i=e[i].nx )
        {
            int v=e[i].v ;
            if(dep[v]==dep[x]+1 && e[i].w >0)
            {
                int t=dfs(v,min(flow,e[i].w ));
                e[i].w -=t;
                e[i^1].w +=t; 
                flow-=t,ans+=t;
            }
            if(!flow) break;
        }
        if(!ans) dep[x]=0;
        return ans;
    }
    
    int aans;
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&s,&ed);
        int u,v,w;
        while(m--)
            scanf("%d%d%d",&u,&v,&w),add(u,v,w),add(v,u,0);
        
        while(bfs())
            aans+=dfs(s,inf);
        printf("%d
    ",aans);
        
        return 0;
    }
  • 相关阅读:
    国外可用的谷歌地图(可根据地址搜索经纬度)
    后台css框架(自用)
    DBHelp类sql分页(自用笔记)
    定制C++高效安全的运行时动态类型转换
    C++11右值引用和std::move语句实例解析
    浏览器内核-Webkit
    获取股票历史数据和当前数据的API
    从浏览器启动应用程序
    一个实时获取股票数据的安卓应用程序
    C++数据类型总结
  • 原文地址:https://www.cnblogs.com/xwww666666/p/11296828.html
Copyright © 2011-2022 走看看