POJ 1273 Drainage Ditches 最大流

这道题用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;
}

  

原文地址:https://www.cnblogs.com/heisenberg-/p/6417454.html