Template is very important.
Maybe someone always mark a wrong template or mark a long template.
Maybe someone always thinks that his template has a very low speed.
A good template can give you a better life ,a hippier mark_sense (and give you higher score)
But,never mind!
Our goal is faster,higher and stronger!
There are several network_flows_template I will show you.
They all have the highest speed and the shortest length
1.max flow
a.hlpp
version one:
the one has frenzied optimization
length:46 lines
speed:44 ms in total
#include<cstdio> using namespace std; #define getchar() (S==T&&(T=(S=BB)+fread(BB,1,1<<15,stdin),S==T)?EOF:*S++) char BB[1<<15],*S=BB,*T=BB; #define cchar register char #define cint register int #define cbool register bool template<class TT>inline void cin(TT&x){ static char c;static int y; for(c=getchar(),x=0,y=1;c<48||57<c;c=getchar())if(c=='-')y=-1; for(;48<=c&&c<=57;c=getchar())x=((x+(x<<2))<<1)+(c^'0'); x*=y;}//an interesing quick_reader void outint(int x){if(x>=10) outint(x/10);putchar(x%10+'0');} typedef int arr[10005]; typedef int ard[200005]; inline int min(cint a,cint b){return a<b?a:b;} int tot=1,n,qhead,tail; arr head,cur,num,dis,pre,Q; ard c,to,next; void ae(cint u,cint v,cint w){ c[++tot]=w;to[tot]=v; next[tot]=head[u];head[u]=tot;} int ar(cint s,cint t){cint flow=1e9,p; for(p=t;p!=s;p=to[pre[p]^1])flow=min(flow,c[pre[p]]); for(p=t;p!=s;p=to[pre[p]^1])c[pre[p]]-=flow,c[pre[p]^1]+=flow;return flow;} void bfs(int s){cint now,p;Q[tail++]=s;dis[s]=1; while(qhead<tail){now=Q[qhead++]; for(p=head[now];p;p=next[p]) if(!dis[to[p]])dis[to[p]]=dis[now]+1,Q[tail++]=to[p];}} int MAXflow(cint s,cint t){cbool ok; cint ans=0,x=s,m,p,i;bfs(t); for(i=1;i<=n;i++)num[dis[i]]++; for(i=1;i<=n;i++)cur[i]=head[i]; while(dis[s]<=n){ok=false;if(x==t)ans+=ar(s,t),x=s; for(p=cur[x];p;p=next[p]) if(c[p]>0&&dis[x]==dis[to[p]]+1){ ok=true,cur[x]=p,pre[to[p]]=p,x=to[p];break;} if(!ok){if(--num[dis[x]]==0)break;m=n; for(p=head[x];p;p=next[p]) if(c[p]>0)m=min(m,dis[to[p]]); num[dis[x]=m+1]++;cur[x]=head[x]; if(x!=s)x=to[pre[x]^1];}}return ans;} int main(){cint a,b,c,m,s,t;cin(n),cin(m),cin(s),cin(t); for(cint i=0;i<m;i++)cin(a),cin(b),cin(c),ae(a,b,c),ae(b,a,0); outint(MAXflow(s,t));return 0; }
Well ,it's not a real_hlpp
The true code is here
version two:
length:50 lines
speed:610 ms in total
Well,a little slow,but never mind.
Maybe we can only believe the theoretical complexity.
#include<cstdio> #include<vector> #include<cstring> using namespace std; const int MAXN=1000015; #define getchar() (W==C&&(C=(W=BB)+fread(BB,1,1<<15,stdin),W==C)?EOF:*W++) char BB[1<<15],*W=BB,*C=BB; template<class TT>inline void cin(TT&x){static char c;static int y; for(c=getchar(),x=0,y=1;c<48||57<c;c=getchar())if(c=='-')y=-1; for(;48<=c&&c<=57;c=getchar())x=((x+(x<<2))<<1)+(c^'0');x*=y;} void outint(int x){if(x>=10) outint(x/10);putchar(x%10+'0');} template<class T=int> struct HLPP{ struct Node{int u,v,index;T c,f; Node(int u,int v,int c,const T&f,const T&index):u(u),v(v),c(c),f(f),index(index){}}; vector<Node>edge[MAXN];vector<int>q[MAXN]; int dis[MAXN],cnt[MAXN+1],pos,n;T exc[MAXN];bool act[MAXN]; inline void addEdge(int u,int v,const T&c){ edge[u].push_back(Node(u,v,c,0,edge[v].size())); if(u==v)edge[u].back().index++; edge[v].push_back(Node(v,u,0,0,edge[u].size()-1));} inline void enqueue(int v){ if(!act[v]&&exc[v]>0&&dis[v]<n)act[v]=true,q[dis[v]].push_back(v),pos=max(pos, dis[v]);} inline void push(Node &e){register T amt=min(exc[e.u],e.c-e.f); if(dis[e.u]==dis[e.v]+1&&amt>0) e.f+=amt,edge[e.v][e.index].f-=amt,exc[e.v]+=amt,exc[e.u]-=amt,enqueue(e.v);} inline void gap(int k){for(register int v=0;v<n;v++) if(dis[v]>=k)cnt[dis[v]]--,dis[v]=max(dis[v],n),cnt[dis[v]]++,enqueue(v);} inline void relabel(int v){cnt[dis[v]]--,dis[v]=n; for(register int i=0;i<edge[v].size();i++){Node *e=&edge[v][i]; if (e->c - e->f>0)dis[v]=min(dis[v],dis[e->v]+1);}cnt[dis[v]]++,enqueue(v);} inline void discharge(int v){ for(register int i=0;i<edge[v].size();i++){Node &e=edge[v][i];if(exc[v]>0)push(e);else break;} if(exc[v]>0){if(cnt[dis[v]]==1)gap(dis[v]);else relabel(v);}} inline T getMaxflow(int s,int t){pos=0; for (register int i=0;i<edge[s].size();i++)exc[s]+=edge[s][i].c; cnt[0]=n;enqueue(s);act[t]=true; while(pos>=0){ if(!q[pos].empty()){register int v=q[pos].back();q[pos].pop_back();act[v]=false;discharge(v);} else pos--;}return exc[t];} void init(int n){ memset(edge,0,sizeof(vector<Node>)*(n+1));memset(exc,0,sizeof(T) * (n + 1)); memset(q,0,sizeof(vector<int>)*(n+1));memset(act,0,sizeof(bool)*(n+1)); memset(cnt,0,sizeof(int)*(n+2));memset(dis,0,sizeof(int)*(n+1));this->n=n;} }; HLPP<> a; int main(){int n,m,s,t,t1,t2,t3; cin(n),cin(m),cin(s),cin(t);a.init(n); for(int i=0;i<m;i++)cin(t1),cin(t2),cin(t3),a.addEdge(t1,t2,t3); outint(a.getMaxflow(s,t));}
version three
length:40 lines
speed:608 lines in total
also a little slow
#include<cstdio> #include<cstring> #include<vector> #include<queue> using namespace std; int s,t; #define getchar() (S==T&&(T=(S=BB)+fread(BB,1,1<<15,stdin),S==T)?EOF:*S++) char BB[1<<15],*S=BB,*T=BB; #define cint register int template<class TT>inline void cin(TT&x){static char c;static int y; for(c=getchar(),x=0,y=1;c<48||57<c;c=getchar())if(c=='-')y=-1; for(;48<=c&&c<=57;c=getchar())x=((x+(x<<2))<<1)+(c^'0');x*=y;} void outint(cint x){if(x>=10) outint(x/10);putchar(x%10+'0');} const int maxn=10001; const int maxm=100001; const int inf=2147483646; struct edge{int v,w,nxt;}e[maxm<<1]; int h[maxn],tot,d[maxn],n,m,prs[maxn],gap[maxn]; bool able[maxn]; void add(cint u,cint v,cint w) {e[++tot]=(edge){v,w,h[u]};h[u]=tot;e[++tot]=(edge){u,0,h[v]};h[v]=tot;} struct cmp{int x,h; cmp(cint x=0,cint h=0):x(x),h(h){} inline bool operator<(const cmp &a)const{return h<a.h;} }; priority_queue<cmp> pq; bool push(cint x,cint y,cint p) {cint w=min(prs[x],e[p].w);e[p].w-=w,e[p^1].w+=w,prs[x]-=w,prs[y]+=w;return w;} void Gap(cint l,cint s,cint t){for(cint i=1;i<=n;++i)if(i!=s&&i!=t&&l<d[i]&&d[i]<=n)d[i]=n+1;} int maxflow(cint s,cint t){while(!pq.empty())pq.pop(); memset(prs,0,sizeof prs),memset(d,0,sizeof d),memset(gap,0,sizeof gap); d[s]=n,prs[s]=inf,pq.push(cmp(s,d[s])); while(!pq.empty()){cint x=pq.top().x;pq.pop(); if(!prs[x]) continue; for(cint i=h[x],v=e[i].v;i;i=e[i].nxt,v=e[i].v) if((x==s||d[x]==d[v]+1)&&push(x,v,i)&&v!=t&& v!=s)pq.push(cmp(v,d[v])); if(x!=s&&x!=t&&prs[x]){ if(!(--gap[d[x]]))Gap(d[x],s,t);++gap[++d[x]]; pq.push(cmp(x,d[x]));}}return prs[t];} int main(){int x,y,w;cin(n),cin(m),cin(s),cin(t);tot=1; for (int i=1;i<=m;++i){cin(x),cin(y),cin(w);if(!w)continue;add(x,y,w);}int ans=maxflow(s,t); outint(ans);return 0;}
b.sap
length:36 lines
speed:31 ms in total
#include <cstdio> #include <cstring> #include <queue> #define MAXN 10010 #define MAXM 200010 #define INF 1073741823 #define getchar() (S==T&&(T=(S=BB)+fread(BB,1,1<<15,stdin),S==T)?EOF:*S++) char BB[1<<15],*S=BB,*T=BB; using namespace std; int n,m,A,B,C,sz=1,s,t; int to[MAXM],v[MAXM],pre[MAXM],las[MAXN],H[MAXN],cur[MAXN],gap[MAXN]; queue<int>Q; int inline read(){int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;} void outint(int x){if(x>=10) outint(x/10);putchar(x%10+'0');} void ins(int a,int b,int c){ sz++;to[sz]=b;v[sz]=c;pre[sz]=las[a];las[a]=sz; sz++;to[sz]=a;v[sz]=0;pre[sz]=las[b];las[b]=sz;} void bfs(){Q.push(t);memset(H,-1,sizeof(H));memset(gap,0,sizeof(gap)); H[t]=0;gap[0]=1; while(!Q.empty()){int tmp=Q.front();Q.pop(); for (int i=las[tmp];i;i=pre[i]) if (H[to[i]]==-1)H[to[i]]=H[tmp]+1,gap[H[to[i]]]++,Q.push(to[i]);}} int dfs(int x,int F){if (x==t)return F; int used=0,w; for(int i=cur[x];i;i=pre[i]) if(v[i]>0&&H[to[i]]+1==H[x]){w=min(v[i],F-used),w=dfs(to[i],w); v[i]-=w,v[i^1]+=w,used+=w; if (v[i]>0) cur[x]=i;if (F==used) return F; }gap[H[x]]--; if (!gap[H[x]]) H[s]=n+2; gap[++H[x]]++;cur[x]=las[x];return used;} int SAP(){int ans=0;for (int i=1;i<=n;i++)cur[i]=las[i];while(H[s]<n+2)ans+=dfs(s,INF);return ans;} int main(){n=read(),m=read(),s=read(),t=read(); for(int i=1;i<=m;i++)A=read(),B=read(),C=read(),ins(A,B,C); bfs();outint(SAP());return 0;}
c.dinic
the one with a little optimization
length:48 lines
speed:47 ms in total
#include<cstdio> #include<cstring> #include<queue> using namespace std; int n,m,s,t,cnt,cur[10002],head[10002],num[10002],gap[10002]; int a[10002],fa[10002],Min[10002],d[10002],ans,q[10002],l; bool f[10002]; int ch_top=1e7; char ch[10000000],*now_r=ch; typedef struct{int flow,cap,nex,to;}bian; bian p[200002]; void add(int u,int v,int w){ p[cnt].cap=w;p[cnt].to=v;p[cnt].nex=head[u];head[u]=cnt++; p[cnt].cap=0;p[cnt].to=u;p[cnt].nex=head[v];head[v]=cnt++; } void bfs(int s){memset(d,-1,sizeof(d));l=0;int u;d[t]=0;q[l++]=t; for(int i=0;i<l;i++){u=q[i];gap[d[u]]++; for (int j=head[u];j!=-1;j=p[j].nex) if (p[j^1].cap>p[j^1].flow && d[p[j].to]==-1) d[p[j].to]=d[u]+1,q[l++]=p[j].to;}} int dfs(){int now=s;a[now]=0;Min[now]=1e9; while(1){ccj: if (Min[now] && now!=t && d[s]<n){ if(!f[now])f[now]=1; else cur[now]=p[cur[now]].nex; for (int&i=cur[now];i!=-1;i=p[i].nex) if (p[i].cap>p[i].flow && d[p[i].to]+1==d[now]){ num[p[i].to]=i;a[p[i].to]=0;fa[p[i].to]=now; Min[p[i].to]=min(Min[now],p[i].cap-p[i].flow); now=p[i].to;f[p[i].to]=0;goto ccj;}} if (Min[now] && now!=t && d[s]<n){ if(--gap[d[now]]==0)d[s]=n; else{int Minn=n-1; for (int i=head[now];i!=-1;i=p[i].nex) if (p[i].cap>p[i].flow)Minn=min(d[p[i].to],Minn); gap[d[now]=Minn+1]++;cur[now]=head[now];f[now]=0;}} if(now==s)return a[s];if(now==t)a[now]=Min[now]; p[num[now]].flow+=a[now];p[num[now]^1].flow-=a[now]; a[fa[now]]+=a[now];Min[fa[now]]-=a[now];now=fa[now];}} int read(){int x=0; while(*now_r<48)++now_r;for(x=*now_r-48;*++now_r>=48;) x=(x<<1)+(x<<3)+*now_r-48;return x;} int main(){fread(ch,1,ch_top,stdin); n=read();m=read();s=read();t=read(); memset(head,-1,sizeof(head));int u,v,w; for (int i=0;i<m;i++)u=read(),v=read(),w=read(),add(u,v,w); bfs(s);for(int i=1;i<=n;i++){f[i]=0;cur[i]=head[i];} while(d[s]<n)ans+=dfs();printf("%d",ans);return 0;}
2.min fee_max flaw
spfa
length:46 lines
speed:481ms in total
#include<bits/stdc++.h> using std::min; #define getchar() (W==C&&(C=(W=BB)+fread(BB,1,1<<15,stdin),W==C)?EOF:*W++) char BB[1<<15],*W=BB,*C=BB; template<class TT>inline void cin(TT&x){ static char c;static int y; for(c=getchar(),x=0,y=1;c<48||57<c;c=getchar())if(c=='-')y=-1; for(;48<=c&&c<=57;c=getchar())x=((x+(x<<2))<<1)+(c^'0'); x*=y;}//an interesing quick_reader #define oo 1000000000 #define N 10100 #define M 200100 int n,m,S,T,i,x,y,f,c,t[N]; struct edge{int to,next,f,cost;}l[M];int e; #define add(x,y,f,c) {l[++e]=(edge){y,t[x],f,c};t[x]=e;} int g[N],tot,h[N],_t[N],base,now,rt,head[N],next[N],*dy[N]; #define fu(x,y) {dy[y]=&x;x=y;} #define _fu(x,y) {dy[y]=x;*x=y;} void merge(int &x,int y){ if (g[x]<g[y]){fu(next[y],head[x]) fu(head[x],y) } else {fu(next[x],head[y]) fu(head[y],x) ;x=y;}} void merges(int &x){int y=next[x],r;while (y) r=next[y],merge(x,y),y=r; } bool spfa(){for (i=1;i<=n;++i)g[i]=oo;g[rt=T]=0; do{x=rt;merges(rt=head[rt]); dy[x]=0,next[x]=head[x]=0,base=g[x]; for(_t[x]=i=t[x];i;i=l[i].next) if(l[i^1].f&&g[y=l[i].to]>(now=base-l[i].cost+h[x]-h[y])) { if(now>g[S])continue;g[y]=now; if (y!=rt) { if (dy[y]!=0) _fu(dy[y],next[*dy[y]]) else if (!rt) {rt=y;continue;}merge(rt,y); }}}while (rt);if(g[S]==oo) return 0; for(x=1;x<=n;++x)h[x]+=g[x];return 1; }bool in[N]; void outint(int x){if(x>=10) outint(x/10);putchar(x%10+'0');} int ansf=0,ansc=0; int dfs(int x,int f){if(x==T)return f; in[x]=1;int f0=f,del,y; for (int &i=_t[x];i;i=l[i].next) if (l[i].f&&(!in[y=l[i].to])&&(l[i].cost==h[x]-h[y])) {del=dfs(y,min(l[i].f,f)); l[i].f-=del;l[i^1].f+=del;f-=del; if (!f) {in[x]=0;return f0;} }in[x]=0;return f0-f;} int main(){cin(n);cin(m);cin(S);cin(T);e=1; for (i=1;i<=m;++i) {cin(x);cin(y);cin(f);cin(c); add(x,y,f,c) add(y,x,0,-c)} while (spfa())f=dfs(S,oo),ansf+=f,ansc+=f*h[S];outint(ansf);putchar(' ');outint(ansc); }