題目大意就不說了是一道裸的網路流中的最大流問題,可以用增廣路演算法來做,即EDMONDS-KARP演算法。 讀入會有多組資料,每一組先有N和M,N表示圖中邊的條數,M表示圖中節點的個數,接下來有N行資料,每行有三個數 S ,E, C 表示一條邊的起點,終點和邊上的容量,注意是有向邊,而且有重邊;
好了題目就是這樣,還是說一下這個演算法吧,這個演算法其實是很暴力的。。他每次只是用BFS找到一條路,使得在這條路上的每一條邊的殘流量(****即容量與流量(**流量就是實際使用的容量有正負的,如果從A到B 的流量是c,那麼從B到A的流量就是-c因為方向相反嘛,是吧?**)之差******)都大於0(*******其中殘流量就是經過使用後這條邊上還剩餘的可使用流量,是有向的,比如從v到u的容量是c,從u到v的容量是零,從v到u的流量是F,那麼從u到v的流量就是-F,於是從v到u的殘流量就是c-F,從u到v的殘流量就是0-(-F)=F(************這個殘流量實際是會變大的,是吧?因為本來不能把東西從U運到V的但是,你把東西從v運到u後,我就可以等效的認為可以把東西從u運到v了,為什嗎?想一想其實很簡單,因為假設你想把5個東西從v往u運,而實際上你只運了2個,那我就可以這樣說,你從v往u運了5個東西而我從u往v運了3個東西,這樣結果是不是等價的????是吧,這就是殘流量的神奇了***********)。 這些概念一定要龍清楚而且要知道怎麼算*****)
啊,注釋好像略多額,好吧繼續說那個,找到了一條殘流量都大於0的路徑。這說明了什麼呢?這條路?那就是這條路上可以運送東西?那可以運送多少東西呢?當然是這條路上的最小的殘留量啊,是吧?想想其實很簡單,如果不是最小的,那你把東西運到最小的殘流量的那條邊上的時候,他肯定就運不過去啊。
這樣也知道運多少了,那就運唄,運的時候就更新一下整條路上的流量就行,注意正反的流量都需要更新。
然後就重複這個找路得過程就行了。直到找不到整條路的最小殘流量都大於0路徑,那麼演算法就結束了
/*********PRO: POJ 1273TIT: Drainage DitchesDAT: 2013-08-12AUT: UKeanEMA: huyocan@163.comALG: Edmonds_Karp*********/#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<queue>#define INF 1e9using namespace std;queue<int> que;//廣搜需要使用的隊列int N,M;//N是邊數,M是點數int s,t;//源點和匯點int flow[205][205];//流量int p[205];//廣搜記錄路徑的父節點數組int a[205];//路徑上的最小殘流量int cap[205][205];//容量網路int ans;int read(){memset(cap,0,sizeof(cap));for(int i=0;i<N;i++){int sta,en,ca;cin>>sta>>en>>ca;cap[sta][en]+=ca;//這樣就可以處理重邊了}s=1;t=M;//s是源點,t是匯點return 1;}void deal()//最大流演算法{memset(flow,0,sizeof(flow));//初始化流量ans=0;//最大流while(1){memset(a,0,sizeof(a));a[s]=INF;que.push(s);while(!que.empty())//廣搜找到增廣路,就是那個最小的殘流量大於零的路徑{int u=que.front();que.pop();for(int v=1;v<=M;v++)if(!a[v]&&cap[u][v]-flow[u][v]>0)//cap[u][v]-flow[u][v] 表示殘流量,//擴張新的的節點!a[v]確保該節點沒被訪問過,殘流量大於0確保找的的路徑符合要求{p[v]=u;//用來記錄v的父親,儲存路徑que.push(v);//入隊a[v]=min(a[u],cap[u][v]-flow[u][v]);//記錄路徑上的最小殘流量}}if(a[t]==0) break;//如果找不到路徑最小殘流量大於0的路徑了就結束演算法for(int u=t;u!=s;u=p[u])//迭代找迴路徑修改,路徑上的流量{flow[p[u]][u]+=a[t];//更新正向的流量flow[u][p[u]]-=a[t];//更新方向流量}ans+=a[t];//增加最大流}cout<<ans<<endl;}int main(){while(cin>>N>>M){read();deal();}return 0;}