zoukankan      html  css  js  c++  java
  • 最大流Dinic

    最近被济南打自闭了,要学习一波图论和数学方面的知识了

    推荐一波大佬的知乎

    Pecco

    一道模板题
    洛谷p1343

    将人看成流量
    所以每次最多的人数就相当于求一次最大流就OK了

    #include<bits/stdc++.h>
    using namespace std;
    using ll = long long;
    const int INF = INT_MAX;
    struct Edge{
        int to, c;
        int next;
        Edge(){
            to = 0;
            c = 0;
            next = 0;
        };
    
    };
    const int MAXN= 1e4+10;
    const int N = 205;
    Edge edges[MAXN];
    int head[N];
    
    int cnt =1;
    void add(int from, int to, int c){
        cnt += 1;
        edges[cnt].to = to;
        edges[cnt].next = head[from];
        edges[cnt].c = c;
        head[from] = cnt;
        
    }
    int s,t;
    int n,m;
    int level[N], cur[N];
    
    bool bfs(){ //当前的图进行分层
        memcpy(cur, head, sizeof head);
        memset(level, -1, sizeof level);
        level[s]=0;
        queue<int> que;
        que.push(s);
        while(!que.empty()){
            int p = que.front();
            que.pop();
            for(int eg=head[p]; eg; eg=edges[eg].next){
                int to = edges[eg].to, c = edges[eg].c;            
                if(c && level[to]==-1)
                    level[to]=level[p]+1, que.push(to);
    
            }
        }
        return level[t]!=-1; 
    }
    
    int dfs(int p=s, int flow = INF){
        if(p==t) 
            return flow;
    
        int rem = flow;
        for(int eg = cur[p]; eg&&rem; eg = edges[eg].next){
            cur[p]=eg; //被增广过的边不会再被增广,因为分层之后尽量使用的
            int to = edges[eg].to, c = edges[eg].c;
            if(c && level[to]==level[p]+1){ //往下一层增广
                int c_flow = dfs(to, min(c, rem));  //管道内的较小的被限制
                rem -= c_flow;
                edges[eg].c -= c_flow;
                edges[eg^1].c += c_flow;
    
            }   
        }
        return flow - rem;//增广掉的流量就是流
    }
    ll dinic(){
        ll ans = 0;
        while(bfs()){
            ans += dfs(); 
        }
        return ans;
    
    }
    int main(){
        // freopen("in.dat", "r", stdin);
        memset(head, 0, sizeof head);
        int x;
        cin>>n>>m>>x;
        s = 1;
        t = n;
        int from, to, c;
        for(int i=0; i<m; i++){
            cin>>from>>to>>c;
            add(from, to, c);  
            add(to, from, 0); 
        }
        ll ans = dinic();
        if(ans==0){
            cout<<"Orz Ni Jinan Saint Cow!"<<endl;
            return 0;
        }
        cout<<ans<<" "<<(x/ans + (x%ans!=0))<<endl;
        return 0;
    }
    
  • 相关阅读:
    霍夫直线检测进行复杂环境的树干提取
    matlab工具箱之人眼检测+meanshift跟踪算法--人眼跟踪
    deep learning 练习 牛顿法完成逻辑回归
    deep learning 练习 多变量线性回归
    deep learning 练习1 线性回归练习
    关于移动端键盘弹出
    关于Redux
    docker registry的CI规划
    建立自己的私有docker(ssl&login auth)
    逻辑编程
  • 原文地址:https://www.cnblogs.com/Crossea/p/14212951.html
Copyright © 2011-2022 走看看