网络流黑科技

太无聊了就来写博客吧。

想起了很久以前看到的网络流黑科技。

可以优化dinic复杂度,虽然还是过不了loj上那个毒瘤网络流,但是可以拿88分。

大致就是先确定最大流的上界,设为x

再从高到低枚举二的幂,只跑残量网络上大于该幂的边,计入流量。

好像可以优化复杂度。

loj127 88分代码

#pragma GCC optimize(3)
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#include <bits/stdc++.h>
using namespace std;
const int INF=1e9,T=1210;
struct edge{
    int y,cap,op;
    edge(int y,int cap,int op):y(y),cap(cap),op(op){
    }
};
vector<edge> g[T];
int buf;
int d[T],cur[T],s,t,n,m;
bool bfs(){
    queue<int> q;
    memset(cur,0,(n+1)*sizeof(*cur));
    memset(d,0,(n+1)*sizeof(*d));
    //cout<<"be"<<t<<" "<<d[1]<<" "<<d[2]<<" "<<d[3]<<" "<<d[4]<<" "<<d[5]<<" "<<d[t]<<endl;
    //getchar();
    q.push(s); d[s]=1;
    while (!q.empty()){
        int x=q.front(); q.pop();
        for (size_t i=0; i<g[x].size(); ++i){
            edge e=g[x][i];
            if (e.cap>=buf&&!d[e.y]){
                d[e.y]=d[x]+1;
                q.push(e.y);
            }
        }
    }
    //cout<<t<<" "<<d[1]<<" "<<d[2]<<" "<<d[3]<<" "<<d[4]<<" "<<d[5]<<" "<<d[t]<<endl;
    return d[t];
}
void add(int x,int y,int cap){
    //cerr<<x<<" "<<y<<" "<<cap<<endl;
    g[x].push_back(edge(y,cap,g[y].size()));
    //g[y].push_back(edge(x,0,g[x].size()-1));
}
int dfs(int x,int flow){
    if (x==t) return flow;
    int past=flow;
    for (int &j=cur[x]; j<g[x].size(); ++j){
        edge &e=g[x][j]; int hv;
        if (e.cap>=buf&&d[e.y]==d[x]+1&&(hv=dfs(e.y,min(flow,e.cap)))){
            e.cap-=hv;
            //g[e.y][e.op].cap+=hv;
            if (!(flow-=hv)) break;
        }
    }
    if (past==flow) d[x]=0;
    return past-flow;
}
int maxflow(){
    int ans=0;
    while (bfs()){
        int ttt;
        while (ttt=dfs(s,INF)) ans+=ttt;
    }
    return ans;
}
namespace io {
  const int SIZE = 1e6;
  char buff[SIZE];
  char *l = buff, *r = buff;
  void init() {
    l = buff;
    r = l + fread(buff, 1, SIZE, stdin);
  }
  char gc() {
    if (l == r) init();
      return *(l++);
  }
  void read(int &x) {
    x = 0;
    char ch = gc();
    while(!isdigit(ch)) ch = gc();
    while(isdigit(ch)) x = x * 10 + ch - '0', ch = gc();
  }
}using io::read;
signed main(){
    read(n); read(m); read(s); read(t);
    for (int i=1; i<=m; ++i){
        int x,y,b;
        read(x); read(y); read(b);
        add(x,y,b);
    }
    int ret=0;
    for (buf=1<<30; buf; buf>>=1) ret+=maxflow();
    printf("%d
",ret);
}
原文地址:https://www.cnblogs.com/Yuhuger/p/9821325.html