最大流EK和Dinic算法
EK算法
最朴素的求最大流的算法。
做法:不停的寻找增广路,直到找不到为止
代码如下:
@Frosero
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#define INF 0x3f3f3f3fusing namespace std;
int n,m;
int cap[202][202],flow[202][202],mf[202],pre[202];//cap为网络的容量 flow为现在的流量 //mf[i]为原点到点i的最大流量 pre[i]为增广路上i点上一个点int EK(int s,int t){memset(flow,0,sizeof(flow));queue<int>q;int ans = 0;while(1){while(!q.empty()) q.pop(); q.push(s);memset(mf,0,sizeof(mf));mf[1] = INF;while(!q.empty()){int u = q.front(); q.pop();for(int i=1;i<=m;i++)if(!mf[i] && flow[u][i] < cap[u][i]){pre[i] = u;q.push(i);mf[i] = min(mf[u],cap[u][i] - flow[u][i]);}}if(mf[t] == 0) break;ans += mf[t];for(int i=t;i!=s;i=pre[i]){flow[pre[i]][i] += mf[t];flow[i][pre[i]] -= mf[t];}}return ans;
}int main(){while(scanf("%d %d",&n,&m)!=EOF){memset(cap,0,sizeof(cap));memset(flow,0,sizeof(flow));int u,v,w;while(n--){scanf("%d %d %d",&u,&v,&w);cap[u][v] += w;}printf("%d\n",EK(1,m));}
}
Dinic算法
Dinic的优化部分就是给残留网络生成一个层次图,然后尽量的利用层次图后再形成新的层次图。
理论上Dinic和EK算法的时间复杂度差不多,但是事实上Dinic算法要好得多。
代码如下:
@Frosero
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#define INF 0x3f3f3f3fusing namespace std;int n,m,flow[202][202],cap[202][202];
int dis[202];//flow为现在的流量 cap为网络的容量//dis为点的层次bool bfs(){ //形成层次图memset(dis,-1,sizeof(dis));dis[1] = 0;queue<int>q; q.push(1);while(!q.empty()){int u = q.front(); q.pop();for(int i=1;i<=m;i++)if(dis[i] == -1 && flow[u][i] < cap[u][i]){dis[i] = dis[u] + 1;q.push(i);}}if(dis[m] == -1) return false;else return true;
}int dfs(int s = 1,int f = INF){ //利用层次图不断寻找增广路if(s == m || f == 0) return f;int ans = 0;for(int i=1;i<=m;i++)if(dis[i] == dis[s] + 1){int a = dfs(i,min(f,cap[s][i] - flow[s][i]));if(a == 0) continue;flow[s][i] += a;flow[i][s] -= a;ans += a;f -= a;if(f <= 0) break;}return ans;
}int dinic(){ //Dinic主过程int ans = 0;while(bfs()){ans += dfs();}return ans;
}int main(){while(scanf("%d %d",&n,&m)!=EOF){ //本代码假设1为原点 m为汇点memset(flow,0,sizeof(flow));memset(cap,0,sizeof(cap));int u,v,w;while(n--){scanf("%d %d %d",&u,&v,&w);cap[u][v] += w;}printf("%d\n",dinic());}return 0;
}