这道题用dinic会超时 用E_K就没问题 注意输入数据有重边。 POJ1273
dinic的复杂度为O(N*N*M)E_K的复杂度为O(N*M*M)对于这道题,复杂度是相同的。
然而dinic主要依靠Dfs寻找增广路,故而使用了太多次递归,而利用bfs寻找增广路(使用队列而不用递归)的EK等于用栈的方式实现了dinic的递归,所以 大幅提高了效率。
最大流算法的核心就是找到增广路并且增加反向边流量,理解了这个,最大流算法就很简单了。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<vector> #include<queue> using namespace std; const int maxn=200*2,s=1,INF=1e+8; int t,n,m,cap[maxn][maxn],from[maxn],to[maxn],c[maxn],f[maxn],dep[maxn],cur[maxn]; vector<int>po[maxn]; bool bfs() { bool vis[maxn]; memset(vis,0,sizeof(vis)); vis[s]=true; queue<int>q; q.push(s); dep[s]=0; while(!q.empty()) { int np=q.front();q.pop(); if(np==t)return true; for(int i=0;i<po[np].size();i++) { int ne=po[np][i]; int next=to[ne]; if((vis[next])||(c[ne]<=f[ne]))continue; vis[next]=true; dep[next]=dep[np]+1; q.push(next); } } return vis[t]; } int min( int a, int b) { if(a<b)return a; else return b; } int dfs(int now, int flo) { if(now==t||flo==0)return flo; int flow=0; for(int i=cur[now];i<po[now].size();i++) { int ne=po[now][i]; int next=to[ne]; if(dep[next]!=dep[now]+1)continue; if(c[ne]<=f[ne])continue; long long int fd=dfs(next,min(flo,c[ne]-f[ne])); f[ne]+=fd; if(ne>=200)f[ne-200]-=fd; else f[ne+200]-=fd; flow+=fd; flo-=fd; if(flo==0)break; cur[now]++; } return flow; } int d[maxn],fa[maxn]; void find() { memset(d,0,sizeof(d)); d[s]=INF; queue<int>q; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=0;i<po[u].size();i++) { int ne=po[u][i]; int next=to[ne]; if(d[next]!=0||cap[u][next]<=0)continue; d[next]=min(d[u],cap[u][next]); q.push(next); fa[next]=u; if(next==t) { while(!q.empty())q.pop(); return ; } } } } int E_K() { int ans=0; while(true) { find(); ans+=d[t]; if(d[t]==0)break; for(int i=t;i!=s;i=fa[i]) { cap[fa[i]][i]-=d[t]; cap[i][fa[i]]+=d[t]; } } return ans; } int main() {freopen("t.txt","r",stdin); ios::sync_with_stdio(false); while(cin>>n>>m) { t=m; memset(f,0,sizeof(f));memset(c,0,sizeof(c));memset(cap,0,sizeof(cap)); for(int i=0;i<n;i++) { cin>>from[i]>>to[i]>>c[i];po[from[i]].push_back(i);cap[from[i]][to[i]]+=c[i];//原边 from[i+200]=to[i];to[i+200]=from[i];po[to[i]].push_back(i+200);//反向边 } cout<<E_K()<<endl; } return 0; }