#include<bits/stdc++.h> using namespace std; #define ll long long const int maxn=3e5; const int INF=0x3f3f3f3f; struct Edge{ int u,v,cap,flow; }; int n,m,s,t; vector<Edge>edges; vector<int>G[maxn]; int vis[maxn]; int d[maxn]; int cur[maxn]; void init(){ edges.clear(); for(int i=0;i<maxn;i++)G[i].clear(); } int BFS(){ memset(vis,0,sizeof vis); queue<int>Q; Q.push(s); d[s]=0; vis[s]=1; while(!Q.empty()){ int x=Q.front();Q.pop(); for(int i=0;i<G[x].size();i++){ Edge &e=edges[G[x][i]]; if(!vis[e.v] && e.cap>e.flow){ vis[e.v]=1; d[e.v]=d[x]+1; Q.push(e.v); } } } return vis[t]; } void addedge(int u,int v,int cap){ edges.push_back((Edge){u,v,cap,0}); edges.push_back((Edge){v,u,0,0}); m=edges.size(); G[u].push_back(m-2); G[v].push_back(m-1); } int DFS(int x,int a){ if(x==t||a==0)return a; int flow=0,f; for(int& i=cur[x];i<G[x].size();i++){ Edge& e=edges[G[x][i]]; if(d[x]+1==d[e.v] && (f=DFS(e.v,min(a,e.cap-e.flow)))>0){ e.flow+=f; edges[G[x][i]^1].flow-=f; flow+=f; a-=f; if(a==0)break; } } return flow; }; int maxflow(int _s,int _t){ s=_s;t=_t; int flow=0; while(BFS()){ memset(cur,0,sizeof cur); flow+=DFS(_s,INF); } return flow; }
BFS对残量网络进行层次图距离测算,DFS贪婪扩充
DFS(x,a)表示当前位于x节点,有a的最大流到达x
当a为0的时候意味着已经访问过的x的后继点已经可以把a全部输送到终点,那么x的其他后继点就不用再从x访问了
当前弧优化就记录了x点之前被访问过的后继点
//#include<bits/stdc++.h> #include<stdio.h> #include<algorithm> #include<string.h> #include<string> #include<vector> #include<queue> #include<iostream> //#pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; #define ll long long const int maxn=2e5; const int INF=0x3f3f3f3f; int d[maxn], cur[maxn], start, tend; struct node { int to, cap, next; }edge[maxn << 1]; int head[maxn]; bool vis[maxn]; int cnt; void init(){ memset(head,-1,sizeof head); cnt=0; } void addedge(int start, int to, int cap) { edge[cnt].to = to; edge[cnt].cap = cap; edge[cnt].next = head[start]; head[start] = cnt++; } bool BFS() { memset(d, -1, sizeof(d)); int Q[maxn * 2]; int Thead, Ttail; Thead = Ttail = 0; Q[Ttail++] = start;; d[start] = 0; while (Thead<Ttail) { int x = Q[Thead]; if (x == tend)return true; for (int i = head[x]; i != -1; i = edge[i].next) { int temp = edge[i].to; if (d[temp] == -1 && edge[i].cap>0)//没有标记,且可行流大于0 { d[temp] = d[x] + 1; Q[Ttail++] = temp; } } Thead++; } return false;//汇点是否成功标号,也就是说是否找到增广路 } int DFS(int x, int cap) { if (x == tend)return cap; int flow = 0, f; for (int i = head[x]; i != -1; i = edge[i].next) { int temp = edge[i].to; if (d[temp] == d[x] + 1 && edge[i].cap) { f = DFS(temp, min(cap - flow, edge[i].cap)); edge[i].cap -= f; edge[i ^ 1].cap += f; flow += f; if (flow == cap)break; } } if (!flow)d[x] = -2;//防止重搜 return flow; } int maxflow() { int flow = 0, f; while (BFS()) { while ((f = DFS(start, INF))>0) flow += f; } return flow; }
原模板似乎有些低效,补一个高效一些的
链式前向星+数组模拟队列
以后应该会用isap吧。。?