最大流(二)—— SAP算法
直接上代码
#include<vector> #include<cstdio> #include<iostream> #include<cmath> #include<queue> #define numm ch-48 #define pd putchar(' ') #define pn putchar('\n') #define pb push_back #define fi first #define se second #define fre1 freopen("1.txt","r",stdin) #define fre2 freopen("2.txt","w",stdout) using namespace std; template <typename T> void read(T &res) { bool flag=false;char ch; while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true); for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm); flag&&(res=-res); } template <typename T> void write(T x) { if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10+'0'); } const int maxm=8000010; ///有反向边,边数要开两倍 const int maxn=1000010; const int inf=0x3f3f3f3f; const int INF=0x7fffffff; typedef long long ll; struct node { ///链式前向星 ll c; int to,net; }e[maxm]; int head[maxn],cur[maxn],numh[maxn],h[maxn],pre[maxn]; ///head:链式前向星头结点数组 ///cur:当前弧数组 ///numh:GAP优化的统计高度数量数组 ///h:距离标号数组 ///pre:前驱数组 int n,cnt=0; void init() { // cnt=0; // for(int i=1;i<=n;i++) ///单测试用例可不用 // h[i]=0,numh[i]=0; for(int i=1;i<=n;i++) head[i]=-1,pre[i]=-1; } void add(int u,int v,ll c) { e[cnt].to=v; e[cnt].c=c; e[cnt].net=head[u]; head[u]=cnt++; } ll SAP_Max_Flow(int st,int ed) { ll max_flows=0; ///最大流 int i,u=st; numh[0]=n; for(int i=1;i<=n;i++) cur[i]=head[i]; while(h[st]<n) { ///h[st]>=N时,网络中肯定出现了GAP(分层) if(u==ed) { int neck; ///瓶颈 ll minn=INF; for(i=st;i!=ed;i=e[cur[i]].to) if(minn>e[cur[i]].c) { minn=e[cur[i]].c; neck=i; } for(i=st;i!=ed;i=e[cur[i]].to) { int tmp=cur[i]; e[tmp].c-=minn; e[tmp^1].c+=minn; } max_flows+=minn; u=neck; } for(i=cur[u];i!=-1;i=e[i].net) if(e[i].c&&h[u]==h[e[i].to]+1) break; ///寻找可行弧 if(i!=-1) { cur[u]=i; pre[e[i].to]=u; u=e[i].to; } else { if(--numh[h[u]]==0) break; cur[u]=head[u]; int tmp; for(tmp=n,i=head[u];i!=-1;i=e[i].net) if(e[i].c) tmp=min(tmp,h[e[i].to]); h[u]=tmp+1; numh[h[u]]++; if(u!=st) u=pre[u]; ///重标号并从当前点前驱重新增广 } } return max_flows; } int main() { int st,m,ed; read(n),read(m),read(st),read(ed); init(); for(int i=1;i<=m;i++) { int u,v; ll c; read(u),read(v),read(c); add(u,v,c); add(v,u,0); ///建立反向边 } write(SAP_Max_Flow(st,ed)); return 0; } ///SAP算法:GAP优化+当前弧优化
所谓人生,一半惊喜,一半遗憾