HDU1532——Drainage Ditches(網絡流Dinic算法)

Drainage Ditches

點擊打開鏈接http://acm.hdu.edu.cn/showproblem.php?pid=1532

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 14961    Accepted Submission(s): 7109


Problem Description

Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clover patch. This means that the clover is covered by water for awhile and takes quite a long time to regrow. Thus, Farmer John has built a set of drainage ditches so that Bessie's clover patch is never covered in water. Instead, the water is drained to a nearby stream. Being an ace engineer, Farmer John has also installed regulators at the beginning of each ditch, so he can control at what rate water flows into that ditch.
Farmer John knows not only how many gallons of water each ditch can transport per minute but also the exact layout of the ditches, which feed out of the pond and into each other and stream in a potentially complex network.
Given all this information, determine the maximum rate at which water can be transported out of the pond and into the stream. For any given ditch, water flows in only one direction, but there might be a way that water can flow in a circle.

 


Input

The input includes several cases. For each case, the first line contains two space-separated integers, N (0 <= N <= 200) and M (2 <= M <= 200). N is the number of ditches that Farmer John has dug. M is the number of intersections points for those ditches. Intersection 1 is the pond. Intersection point M is the stream. Each of the following N lines contains three integers, Si, Ei, and Ci. Si and Ei (1 <= Si, Ei <= M) designate the intersections between which this ditch flows. Water will flow through this ditch from Si to Ei. Ci (0 <= Ci <= 10,000,000) is the maximum rate at which water will flow through the ditch.

 


Output

For each case, output a single integer, the maximum rate at which water may emptied from the pond.

 


Sample Input

5 4 1 2 40 1 4 20 2 4 20 2 3 30 3 4 10

 


Sample Output

50
解題思路:
這道題用EK或者Dinic算法都可以,這裏小龍人用的是Dinic算法。
首先建造地圖給每個節點分層(比如 1->2, 2->4, 1->3, 3->4, 2->3 這個圖,1是0層,2,3是1層,4是2層),每個節點只能走向下一層的節點,並且這兩個節點有水管。分層分好後,比如有兩條路,依次走這兩條路,選出每條路最小的水管容量,然後用這條路所有水管容量依次減去最小水管容量,並且添加反向容量(反向容量=該水管的流量,至於爲什麼要添加,這裏比較難懂,小龍人建議去問問身邊的大神),返回最小水管容量,兩條路走完後,再次給地圖節點分層(這時,流量達到容量的水管已經爲0,或者說這條路已經不通了),重複上面的步驟,最後直到分層後不能給匯點分層就結束。
代碼實現:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <queue>
#include <vector>

using namespace std;
const int maxn = 205;
const int MAXN = ( 1<<29 );
int m, n;
int mp[maxn][maxn];
int dis[maxn];

bool bfs( int d )                               //用bfs給圖分層;
{
    queue<int>q;
    memset(dis, -1, sizeof(dis));
    dis[d] = 0;
    q.push(d);
    while( !q.empty() )
    {
        int top = q.front();
        q.pop();
        for( int j=1; j<=n; j++ )
        {
            if( dis[j] == -1 && mp[top][j] > 0 )
            {
                dis[j] = dis[top] + 1;           //層數+1;
                q.push(j);
            }
        }
    }
    if( dis[n] > 0 )                             //直到匯點不能分層結束;
        return true;
    return false;
}

int findd( int k, int low )
{
    if( k == n )
        return low;
    int a = 0;
    for( int i=1; i<=n; i++ )
    {
        if( dis[i] == dis[k]+1
           && mp[k][i] > 0
           && ( a = findd( i, min(low, mp[k][i]) )) )     // 用遞歸找到該路的最小容量;
        {
            mp[k][i] -= a;                                // 該路各水管依次減去最小容量;
            mp[i][k] += a;                                // 添加反向容量;
            return a;
        }
    }
    return 0;
}

int main()
{
    while( scanf("%d%d",&m,&n)!=EOF )
    {
        memset(mp, 0, sizeof(mp));
        int si, ei, ci;
        for( int i=0; i<m; i++ )
        {
            scanf("%d%d%d",&si,&ei,&ci);
            mp[si][ei] += ci;                 // 細節注意,這裏必須用疊加,有可能 1->2有兩根水管疊加;
        }
        int ans = 0, temp;
        while(bfs(1))
        {
            while( temp = findd( 1, MAXN ) )
                ans += temp;
        }
        printf("%d\n",ans);
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章