本文中 N为点数,M为边数;
EK: (brute_force) ;
每次bfs暴力找到一条增广路,更新流量,代码如下 :
时间复杂度:O(NM²);
1 #include2 using namespace std; 3 4 struct node{ 5 int next,to,len; 6 }edge[200005]; 7 8 int val[10005],head[200005],vis[10005],from[100005]; 9 int n,m,s,t,ans,inf=2147483647,cnt=1; 10 11 inline void add_edge(int u,int v,int len){ 12 edge[++cnt].to=v; 13 edge[cnt].next=head[u]; 14 edge[cnt].len=len; 15 head[u]=cnt; 16 } 17 18 inline bool bfs(){ 19 queue <int> q; 20 memset(vis,0,sizeof(vis)); 21 val[s]=inf; 22 q.push(s);vis[s]=1; 23 while(q.size()){ 24 int u=q.front(); q.pop(); 25 for(int i=head[u];i;i=edge[i].next){ 26 int v=edge[i].to; 27 if(vis[v]||!edge[i].len)continue; 28 vis[v]=1; q.push(v); 29 from[v]=i; 30 val[v]=min(val[u],edge[i].len); 31 if(v==t)return true; 32 } 33 } 34 return false; 35 } 36 37 inline void update(){ 38 int u=t; 39 while(u!=s){ 40 int p=from[u]; 41 edge[p].len-=val[t]; 42 edge[p^1].len+=val[t]; 43 u=edge[p^1].to; 44 } 45 ans+=val[t]; 46 } 47 48 int main(){ 49 int x,y,z; 50 scanf("%d %d %d %d",&n,&m,&s,&t); 51 for(int i=1;i<=m;i++){ 52 scanf("%d %d %d",&x,&y,&z); 53 add_edge(x,y,z); 54 add_edge(y,x,0); 55 } 56 while(bfs())update(); 57 printf("%d\n",ans); 58 return 0; 59 }
Dinic: 显然,EK算法每次只bfs找到一条增广路径是非常睿智低效的,Dinic算法就是通过dfs 每次找到一张增广网,从而使增广速度加快;
p.s. 当前弧优化:在dfs进行增广时,有些边已经对此次的增广做出了全部的贡献(换言之,他在当前的残量网络中已经没有贡献了),所以就不必再考虑它;
代码如下:
时间复杂度:O(Dinic(N, M)) O(N*M½) ~ O(M*N²);
1 //15owzLy1 2 //Dinic.cpp 3 //2018 10 10 11:51:55 4 #include5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include
二分图:顾名思义,就是可以分成两个部分的图(把点分成两边,同一侧的点只能向另一侧的点连边);
二分图最大匹配:在边中选一个子集,使得每个点最多与该边集中的一个点相连,边数最多的子集即最大匹配;
如何求???
1.匈牙利算法(Hungarian method) : (brute_force) ———— 看代码
将点分为两部分(左右两边);(u在左边,v在右边)
mat[v]=u表示当前与v匹配的点为u;
每次dfs即寻求增广路;
1 //15owzLy1 2 //Hungary.cpp 3 //2018 10 10 17:04:04 4 #include5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include
2.与网络流有何关系????
将源点和左边的点相连,右边的点与汇点相连,流量设为1;
左右点之间的边流量设为一个大于等于1的整数;
此时求出最大流,即为最大匹配;
感性理解一下:最大匹配是在边集中选出一个子集;一个点与该子集中的边相连,与该点与源点或者汇点所连边的流量流满是等效的;
建边过程:
1 inline void jb(int u, int v, int w) { 2 edge[++cnt].to=v; 3 edge[cnt].next=head[u]; 4 edge[cnt].len=w; 5 head[u]=cnt; 6 } 7 int main() { 8 int x, y, z; 9 read(n), read(m), read(s), read(t); 10 for(int i=1;i<=m;i++) { 11 read(x), read(y), read(z); 12 jb(x, y, z), jb(y, x, 0); 13 } 14 Dinic::Dinic(); 15 return 0; 16 }