复习了下网络流,自己手动实现了两种增广路网络流
FF算法,裸的贪心+反向弧
#include <iostream> #include <cstdio> #include <vector> #include <cstring> using namespace std; struct node{ int to,cap,rev;//这里流量为整数 node(int _to,int _cap,int _rev):to(_to),cap(_cap),rev(_rev){} }; //为什么在结构体里面要加入反向边这个属性呢,因为我们用的是邻接表 //虽然你立马知道反向边的起点,,但是你却不知道你在这个起点的链表的位置是多少,我们这里可以记录一下 const int maxn=1005; const int INF=~(0u)>>1; vector<node> G[maxn];int s,t; void add(int u,int v,int cap){ G[u].push_back(node(v,cap,G[v].size()));//rev的索引必然是G[v].size()-1+1,这次一定会加一的嘛 G[v].push_back(node(u,0,G[u].size()-1));//它的反向边先被push必然是u的最后一条边 } bool vis[maxn]; int dfs(int v,int t,int f){ vis[v]=true; if(v==t) return f; int i; for(i=0;i<G[v].size();++i){ node &e=G[v][i]; if(!vis[e.to]&&e.cap>0){ int d=dfs(e.to,t,min(f,e.cap)); if(d>0){ e.cap-=d; G[e.to][e.rev].cap+=d; return d; } } } return 0; } int maxflow(){ int flow=0; for(;;){ memset(vis,0,sizeof(vis)); int f=dfs(s,t,INF); if(f==0) break; flow+=f; } return flow; } int main(){ freopen("testMaxFlow.txt","r",stdin); int n,i,u,v,cap;//读入总边数 scanf("%d",&n); scanf("%d%d",&s,&t); for(i=0;i<n;++i){ scanf("%d%d%d",&u,&v,&cap); add(u,v,cap); } printf("ans:%d\n",maxflow()); return 0; }
Dinic算法,level和iter数组的当前弧优化非常巧妙
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <queue> using namespace std; struct node{ int to,cap,rev; node(int _to,int _cap,int _rev):to(_to),cap(_cap),rev(_rev){} }; const int maxn=1005; vector<node> G[maxn]; int s,t; void add(int u,int v,int cap){ G[u].push_back(node(v,cap,G[v].size())); G[v].push_back(node(u,0,G[u].size()-1)); } bool vis[maxn];//这个可以不要,level数组可以起两个作用,记录层数和是否被访问过,类似于dp数组 int level[maxn],iter[maxn]; void bfs(){ memset(level,-1,sizeof(level)); queue<int> q; q.push(s);int i;level[s]=0; while(!q.empty()){ int u=q.front(); q.pop(); for(i=0;i<G[u].size();++i){ node& e=G[u][i]; if(e.cap>0&&level[e.to]<0){ level[e.to]=level[u]+1; q.push(e.to); } } } //需要得到所有顶点的level信息,一方面起vis的作用,另一方面起到转移的作用 //而且考虑到可能同时存在多个最短增广路 } int dfs(int v,int t,int f){ printf("v:%d t:%d f:%d\n",v,t,f); if(v==t) return f; for(int &i=iter[v];i<G[v].size();++i){ node &e=G[v][i]; if(e.cap>0&&level[e.to]>level[v]){ int d=dfs(e.to,t,min(e.cap,f)); if(d>0){ e.cap-=d; G[e.to][e.rev].cap+=d; return d; } } } return 0;//这里忘记return 0了... } const int INF=~0u>>1; int maxflow(){ int flow=0,f; for(;;){ bfs(); for(int i=0;i<5;++i){ printf("i:%d level:%d\n",i,level[i]); } if(level[t]<0) return flow; memset(iter,0,sizeof(iter)); while((f=dfs(s,t,INF))>0) flow+=f; } } int main(){ freopen("testMaxFlow.txt","r",stdin); int n,i,u,v,cap;scanf("%d",&n); scanf("%d%d",&s,&t); for(i=0;i<n;++i){ scanf("%d%d%d",&u,&v,&cap); add(u,v,cap); } printf("ans:%d\n",maxflow()); return 0; }