Luogu 3376 網路最大流
題目連結:https://www.luogu.org/problemnew/show/P3376
思路:
這道題資料範圍較大,按照鄰接矩陣的方法存邊只能得70分。
還是先考慮求解,只是更換存邊方法。
由於本人對掌握不是很好,於是就沒敢用存邊,聽說很方便?
其實鄰接矩陣比較好寫,在存反向邊和增廣方面。
用鄰接表其實也不難。
對於反向邊,我們邊號需要從0開始,也就是與平常不同,。
然後就可以用異或來做,因為0^1=1,1^1=0,2^1=3,3^1=2,......
然後增光的時候迴圈稍有不同,看程式碼吧。
#include <cstdio> #include <cctype> #include <cstring> #include <iostream> #include <algorithm> #include <queue> static const int MAXN=20050; static const int MAXM=200050; static const int INF=1<<30; using namespace std; struct Edge{ int from,to,val,nextt; }edge[MAXM]; int n,m,s,t,u,v,w,num,maxflow,head[MAXN],res[MAXN],father[MAXN]; queue<int> q; inline int read(){ int x=0;bool sign=false; char alpha=0; while(!isdigit(alpha)) sign|=alpha=='-',alpha=getchar(); while(isdigit(alpha)) x=(x<<1)+(x<<3)+(alpha^48),alpha=getchar(); return sign?-x:x; } inline void addedge(int u,int v,int w){ edge[num].from=u; edge[num].to=v; edge[num].val=w; edge[num].nextt=head[u]; head[u]=num++; } inline bool bfs(int s,int t){ while(!q.empty()) q.pop(); memset(res,0,sizeof(res)); q.push(s); res[s]=INF; while(!q.empty()){ int x=q.front();q.pop(); for(int i=head[x];i;i=edge[i].nextt){ int to=edge[i].to; if(res[to]==0&&edge[i].val){ father[to]=i; res[to]=min(res[x],edge[i].val); q.push(to); } } if(res[t]) return true; } return false; } inline int EK(int s,int t){ while(1){ if(!bfs(s,t)) break; for(int i=t;i!=s;i=edge[father[i]].from){ edge[father[i]].val-=res[t]; edge[father[i]^1].val+=res[t]; } maxflow+=res[t]; } return maxflow; } int main(){ n=read();m=read();s=read();t=read(); for(int i=1;i<=m;i++){ u=read();v=read();w=read(); addedge(u,v,w); addedge(v,u,0); } printf("%d\n",EK(s,t)); return 0; }
之後會更新演算法。