[网络流dinic]日常翻新
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[网络流dinic]日常翻新相关的知识,希望对你有一定的参考价值。
之前的排版简直辣眼睛,重写一遍好了
模板题是草地排水poj1273
网络流的基础思想就是瞎基本搜
但是搜要搜得有技巧,有特色
最简单的搜,无限深搜直到终点
稍微改进一下,宽搜先标号然后按层搜
再改进一下,把某些确定不再使用的点剔除
要点在于建立反向边给自己一个反悔的机会,用^1找到反向边
#include <stdio.h> #include <queue> #include <algorithm> #include <string.h> using namespace std; const int N=205; const int M=405; int m,n,s,last[N],level[N]; struct edge { int v,w,n; }e[M]; void add(int u,int v,int w) { e[s]=(edge){v,w,last[u]},last[u]=s++; e[s]=(edge){u,0,last[v]},last[v]=s++; } int BFS() { memset(level,-1,sizeof(level)); queue<int>q; q.push(1);level[1]=0; while(!q.empty()) { int t=q.front();q.pop(); for (int i=last[t];~i;i=e[i].n) { if(e[i].w&&level[e[i].v]==-1) q.push(e[i].v),level[e[i].v]=level[t]+1; } } return level[n]!=-1; } int DFS(int a,int b) { if (a==n) return b; int r=0; for (int i=last[a];~i&&b>r;i=e[i].n) { if (level[a]+1==level[e[i].v]&&e[i].w) { int t=DFS(e[i].v,min(b-r,e[i].w)); e[i].w-=t;e[i^1].w+=t;r+=t; } } if (!r) level[a]=-1; return r; } int dinic() { int ans=0,tmp; while(BFS())while(tmp=DFS(1,0x3fffffff))ans+=tmp; return ans; } int main() { while(scanf ("%d %d",&m,&n)!=EOF) { memset (last,-1,sizeof(last)); s=0; for (int i=1;i<=m;i++) { int u,v,w; scanf ("%d %d %d",&u,&v,&w); add(u,v,w); //add(v,u,0); } printf ("%d\\n",dinic()); } }
就是这样,喵~
最后一行献给可爱的男孩子们
以上是关于[网络流dinic]日常翻新的主要内容,如果未能解决你的问题,请参考以下文章