1. 程式人生 > 實用技巧 >最大流Dinic

最大流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;
}