#include<bits/stdc++.h> //#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<algorithm> #include<queue> #include<string.h> #include<iostream> #include<math.h> #include<set> #include<map> #include<vector> #include<iomanip> using namespace std; #define ll long long #define pb push_back #define FOR(a) for(int i=1;i<=a;i++) const int inf=0x3f3f3f3f; const int maxn=1e6+9; int num_nodes; //预留超级源给0,所有的点是0到num_nodes-1 int tot; int d[maxn],cur[maxn],source,sink; int p[maxn],num[maxn],vis[maxn]; struct EDGE{ int from,to,cap,flow; }; vector<EDGE>edge; vector<int>G[maxn]; void init(){ edge.clear(); for(int i=0;i<maxn;i++)G[i].clear(); } void addedge(int u,int v,int w){ edge.push_back((EDGE){u,v,w,0}); edge.push_back((EDGE){v,u,0,0}); tot=edge.size(); G[u].push_back(tot-2); G[v].push_back(tot-1); } int bfs(){ //只跑一次初始化原图层次,void也行 memset(vis,0,sizeof vis); queue<int>Q; Q.push(sink); vis[sink]=1; d[sink]=0; while(!Q.empty()){ int u=Q.front(); Q.pop(); int sz=G[u].size(); for(int i=0;i<sz;++i){ EDGE &e=edge[G[u][i]^1]; if(!vis[e.from] && e.cap>e.flow){ vis[e.from]=1; d[e.from]=d[u]+1; Q.push(e.from); } } } return vis[source]; } int augment(){ //遍历处理出的路径 int u=sink,a=inf; while(u!=source){ EDGE &e=edge[p[u]]; a=min(a,e.cap-e.flow); u=edge[p[u]].from; } u=sink; while(u!=source){ edge[p[u]].flow+=a; edge[p[u]^1].flow-=a; u=edge[p[u]].from; } return a; } int maxflow(){ int flow=0; bfs(); //处理出d数组表示层次图 memset(num,0,sizeof num); for(int i=0;i<num_nodes;i++)num[d[i]]++; //各个层次的点有多少个 int u=source; memset(cur,0,sizeof cur); //当前弧编号,前面不行后面也不会用 while(d[source]<num_nodes){ //残量网络可达 if(u==sink){ //增广到终点 flow+=augment(); u=source; } bool advance=false; int sz=G[u].size(); for(int i=cur[u];i<sz;i++){ EDGE &e=edge[G[u][i]]; if(e.cap>e.flow && d[u]==d[e.to]+1){ advance=true; p[e.to]=G[u][i]; cur[u]=i; u=e.to; break; } } if(!advance){ int m=num_nodes-1; int sz=G[u].size(); for(int i=0;i<sz;i++){ if(edge[G[u][i]].cap>edge[G[u][i]].flow){ m=min(m,d[edge[G[u][i]].to]); } } if(--num[d[u]]==0)break; num[d[u]=m+1]++; cur[u]=0; if(u!=source)u=edge[p[u]].from; } } return flow; } /****** main: init(),num_nodes,source,sink ******/