1. 程式人生 > >網絡最大流 dinic算法

網絡最大流 dinic算法

next 發生 mem bfs light ont ems ++ set

一句話題意:給出一個網絡圖,以及其源點和匯點,求出其網絡最大流

//dinic算法;
//時間復雜度O(V^2E); 
#include<bits/stdc++.h>
#define inf 999999
#define maxn 200000
using namespace std;
int n,m,s,t;
int ans=0;

struct Edge
{
   int to,next,w;
};
struct Edge edge[maxn];
int head[maxn],val[maxn],pre[maxn];
int level[maxn];
int cnt=0;

void add(int u,int v,int w)//前向星儲存邊 
{
    edge[cnt].to=v;
    edge[cnt].w=w;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}

int bfs(int s,int t)
{
    queue<int> q;
    q.push(s);
	memset(level,-1,sizeof(level));//一定要從-1開始儲存,如果從0開始存的話由於數組本身就是0,會造成死循環!! 
	level[s]=0;
   while(!q.empty())
   {
     int j=q.front();q.pop();
     for(int i=head[j];~i;i=edge[i].next)
     {
	    int v=edge[i].to;
	    if(level[v]==-1&&edge[i].w)//染色,廣搜求出到達每個點的步數 
	    {
		   level[v]=level[j]+1;
		   q.push(v);
		}
	 }
   }
   return (level[t]==-1) ? 0 : 1;//如果不能達到t就是沒有增廣路,就不進行查找 
}

int dfs(int u,int flow,int v)
{
	  if(u==v)
	    return flow;
	  int rest=0;
	  for(int i=head[u];~i;i=edge[i].next)
	  {
	     int j=edge[i].to;
	     if(level[u]+1==level[j]&&edge[i].w)
	     {
		     int flo=dfs(j,min(edge[i].w,flow-rest),v);     
		     rest+=flo;
			 edge[i].w-=flo;
		     edge[i^1].w+=flo;//如果i=0,則去i+1如果i=1則取0,總之是取反向邊 
		 }
	  }
	  if(!rest)
	    level[u]=-1;
	  return rest;
}

int main()
{
	int u,v,w;
	memset(head,-1,sizeof(head)); 
	cin>>n>>m>>s>>t;
	for(int i=0;i<m;i++)//註意從0開始儲存,否則會發生錯誤 
	{
	   cin>>u>>v>>w;
	   add(u,v,w);//s->t存到2k
	   add(v,u,0);//t->s存到2k-1 
	}
	while(bfs(s,t))
	   while(int tmp=dfs(s,inf,t))
	     ans+=tmp;
	cout<<ans<<endl;
    return 0;
}

網絡最大流 dinic算法