太无聊了就来写博客吧。
想起了很久以前看到的网络流黑科技。
可以优化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); }