1. 程式人生 > >HDU 3549 Flow Problem(最大流裸題,EK解法)

HDU 3549 Flow Problem(最大流裸題,EK解法)

EK現在用起來已經比較熟練了,比較簡單的題目,直接就可以解決,但發現EK,其實效率有些低,是O(V*E^2)的,搞不好,還會超時。同時看別人的部落格,發現用EK的比較少。今天,聽學長講,dinic用的比較多,sap學起來有一定難度,接下來抓緊學一下dinic!

好了,廢話不多說了,進入主題!

原題連結:http://acm.hdu.edu.cn/showproblem.php?pid=3549

題意:在給定的有向圖中,求點1到n的最大流。

注意點:EK兩點之間只能有一條正向邊,而頂點最多隻有15個,邊卻最多有1000條,15*14/2<<1000,顯然兩點間會有重邊。所以處理時,既不是取兩點間邊的最大值,也不是讓新加入的邊覆蓋,而是不斷累加。

下面是比較詳細的註解的程式碼:

#include <iostream>
#include <cstdio>
#include <queue>
#include <string.h> 
using namespace std;
#define arraySize 20
#define inf 1000000000
int capacity[arraySize][arraySize],flow[arraySize][arraySize],max_flow[arraySize],pre[arraySize];
//capacity儲存點之間最大流量,flow儲存點之間當前已經流過的流量 
//max_flow儲存每次遍歷過程中的值,pre記錄查詢過程中每個節點的前一節點,用於後續更新

int Edmonds_Karp(int source,int target)//源點,匯點 
{
	//初始化 
	queue <int> store;
	int ans=0,cur;
	//cur當前節點 
	memset(flow,0,sizeof(flow));
	while(true)//一直尋找增廣路 
	{
	   memset(max_flow,0,sizeof(max_flow));	
	   memset(pre,0,sizeof(pre));
	   store.push(source);
	   max_flow[source]=inf;
	   while(!store.empty())
	   {
   	     cur=store.front();
   	     store.pop();
   	     for(int next=source;next<=target;next++)
   	     {
   	     	//max_flow[next]恰可以用於標記是否訪問過,同時要保證兩點之間還有剩餘流量 
                //這個過程中,可能會出現多條可行路徑,但因為匯點只有一個會被先到達的路徑搶佔,故每個過程只能找到一條
     	    if(!max_flow[next]&&capacity[cur][next]>flow[cur][next])
            {
                 store.push(next);  
                 //如果這兩個點之間的值,比之前的最小值還小,則更新 
                 max_flow[next]=min(max_flow[cur],capacity[cur][next]-flow[cur][next]);
                 //記錄前一個節點,用於後續更新 
                 pre[next]=cur;
 			} 	
	     }
   	   }
   	   //說明已經找不到增廣路了 
   	   if(max_flow[target]==0)break;
	   //更新操作 
   	   for(int u=target;u!=source;u=pre[u])  
        {  
            flow[pre[u]][u]+=max_flow[target];
			//反向邊  
            flow[u][pre[u]]-=max_flow[target];  
        }  
        ans+=max_flow[target]; 
	}
	return ans;
}
int main()
{
	int t,n,m,fm,to,val,cnt=0;
	scanf("%d",&t);
	while(t--)
	{
	  memset(capacity,0,sizeof(capacity));
	  scanf("%d%d",&n,&m);
	  for(int i=1;i<=m;i++)
	  {
  		 scanf("%d%d%d",&fm,&to,&val);
  		 capacity[fm][to]+=val;
  	  }	
  	  printf("Case %d: %d\n",++cnt,Edmonds_Karp(1,n));
	}
	return 0;
}