zoukankan      html  css  js  c++  java
  • 复习了下网络流,自己手动实现了两种增广路网络流

    FF算法,裸的贪心+反向弧

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    using namespace std;
    struct node{
        int to,cap,rev;//这里流量为整数
        node(int _to,int _cap,int _rev):to(_to),cap(_cap),rev(_rev){}
    };
    //为什么在结构体里面要加入反向边这个属性呢,因为我们用的是邻接表
    //虽然你立马知道反向边的起点,,但是你却不知道你在这个起点的链表的位置是多少,我们这里可以记录一下
    
    const int maxn=1005;
    const int INF=~(0u)>>1;
    vector<node> G[maxn];int s,t;
    void add(int u,int v,int cap){
        G[u].push_back(node(v,cap,G[v].size()));//rev的索引必然是G[v].size()-1+1,这次一定会加一的嘛
        G[v].push_back(node(u,0,G[u].size()-1));//它的反向边先被push必然是u的最后一条边
    }
    bool vis[maxn];
    int dfs(int v,int t,int f){
        vis[v]=true;
        if(v==t)  return f;
        int i;
        for(i=0;i<G[v].size();++i){
            node &e=G[v][i];
            if(!vis[e.to]&&e.cap>0){
                int d=dfs(e.to,t,min(f,e.cap));
                if(d>0){
                    e.cap-=d;
                    G[e.to][e.rev].cap+=d;
                    return d;
                }
            }
        }
        return 0;
    }
    int maxflow(){
        int flow=0;
        for(;;){
            memset(vis,0,sizeof(vis));
            int f=dfs(s,t,INF);
            if(f==0) break;
            flow+=f;
        }
        return flow;
    }
    int main(){
        freopen("testMaxFlow.txt","r",stdin);
        int n,i,u,v,cap;//读入总边数
        scanf("%d",&n);
        scanf("%d%d",&s,&t);
        for(i=0;i<n;++i){
            scanf("%d%d%d",&u,&v,&cap);
            add(u,v,cap);
        }
        printf("ans:%d
    ",maxflow());
        return 0;
    }

    Dinic算法,level和iter数组的当前弧优化非常巧妙

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <queue>
    using namespace std;
    struct node{
        int to,cap,rev;
        node(int _to,int _cap,int _rev):to(_to),cap(_cap),rev(_rev){}
    };
    const int maxn=1005;
    vector<node> G[maxn];
    int s,t;
    void add(int u,int v,int cap){
        G[u].push_back(node(v,cap,G[v].size()));
        G[v].push_back(node(u,0,G[u].size()-1));
    }
    bool vis[maxn];//这个可以不要,level数组可以起两个作用,记录层数和是否被访问过,类似于dp数组
    int level[maxn],iter[maxn];
    void bfs(){
        memset(level,-1,sizeof(level));
        queue<int> q;
        q.push(s);int i;level[s]=0;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(i=0;i<G[u].size();++i){
                node& e=G[u][i];
                if(e.cap>0&&level[e.to]<0){
                    level[e.to]=level[u]+1;
                    q.push(e.to);                
                }
            }
        }
        //需要得到所有顶点的level信息,一方面起vis的作用,另一方面起到转移的作用
        //而且考虑到可能同时存在多个最短增广路
    }
    int dfs(int v,int t,int f){
        printf("v:%d t:%d f:%d
    ",v,t,f);
        if(v==t) return f;
        for(int &i=iter[v];i<G[v].size();++i){
            node &e=G[v][i];
            if(e.cap>0&&level[e.to]>level[v]){
                int d=dfs(e.to,t,min(e.cap,f));
                if(d>0){
                    e.cap-=d;
                    G[e.to][e.rev].cap+=d;
                    return d;
                }
            }        
        }
        return 0;//这里忘记return 0了...
    }
    const int INF=~0u>>1;
    int maxflow(){
        int flow=0,f;
        for(;;){
            bfs();
            for(int i=0;i<5;++i){
                printf("i:%d level:%d
    ",i,level[i]);
            }
            if(level[t]<0) return flow;
            memset(iter,0,sizeof(iter));
            while((f=dfs(s,t,INF))>0) flow+=f; 
        }
    }
    int main(){
        freopen("testMaxFlow.txt","r",stdin);
        int n,i,u,v,cap;scanf("%d",&n);
        scanf("%d%d",&s,&t);
        for(i=0;i<n;++i){
            scanf("%d%d%d",&u,&v,&cap);
            add(u,v,cap);
        }
        printf("ans:%d
    ",maxflow());
        return 0;
    }

      

  • 相关阅读:
    mate框架
    【CXF】Apache CXF 简介
    Flex 自定义DataGrid控件
    MYSQL远程登录权限设置
    不要像小贝那样学习C++
    tablesorter,jquery
    Linux系统搭建RabbitMQ
    loadView viewDidLoad viewWillAppear viewWillAppear
    得到图片中的某一部分
    addSubview和insertSubview的区别
  • 原文地址:https://www.cnblogs.com/linkzijun/p/6574822.html
Copyright © 2011-2022 走看看