【poj1273】Drainage Ditches(Dinic)

来源:互联网 发布:mac air airdrop 编辑:程序博客网 时间:2024/05/21 21:36

                                                 Drainage Ditches

Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 76009 Accepted: 29532

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.

昨天,在队长的英明指导下学习了网络流的基本姿势,来写一下这一道裸最大流的题解~

最大流问题的算法还挺多,昨天学习了Dinic算法,感觉这个可以应付大多数问题,不过还是有一丝纠结要不要学Ek和SAP算法=-=(虽然我也不知道她们有什么区别)

题意:n个通道,m个地点,给出每个通道的流量,求出从1点到m点的最大流量(*゚▽゚*)

如果只用深搜来做最大流问题很容易会出现浪费了流量的情况,反正就是求不出最大的情况,所以一个非常神奇的东西就诞生了!反向边!!

从起点开始向终点搜索的过程中,找到一条流量不为0的通路(好像叫增广路),把容量减去流量之后,在相反的方向加一条容量等于流量的反向边就可以解决上面的问题。

不过这是为什么呢,我也说不清楚=-=,反正。。。就是给这条路一个向反方向把流量换回去赢取更大总流量的机会,额,我是这样理解的。

在Dinic算法中,bfs给每一个点分层,然后使用dfs来寻找增广路,上一层只能流向下一层,找完一条就回溯回去找下一条,找不到就重新bfs、dfs循环,知道已经分不了流量不为0的下一层就得到答案(ง •̀_•́)ง     (哦嗦,好厉害的样子

代码驾到!!(因为写代码的时候bug巨多,又总debug不出来,改错的时候只能不停地向网上大佬们的标程靠⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄.

#include #include #include #include #include using namespace std;const int M=210;const int INF=0x3f3f3f3f;int mapp[M][M];int n,m;int vv[M];int bg,ed;int bfs()//给每个点分层{    queuea;    memset(vv,-1,sizeof(vv));    vv[bg]=0;    a.push(bg);    int b;    while(!a.empty())    {        b=a.front();a.pop();        for(int i=1;i<=m ;i++)        {            if(mapp[b][i]>0&&vv[i]==-1)            {                vv[i]=vv[b]+1;a.push(i);            }        }    }    if(vv[ed]!=-1)        return 1;    else        return 0;}int dfs(int u,int Min){    if(u==ed)        return Min;    int t;    for(int i=1;i<=m;i++)    {        if(mapp[u][i]>0&&vv[i]==vv[u]+1&&(t=dfs(i,min(Min,mapp[u][i]))))        {            mapp[u][i]-=t;            mapp[i][u]+=t;//反向边加            return t;        }    }    return 0;}int dinic(){    int ans=0,u;    while(bfs())    {        while(1)        {            u=dfs(1,INF);            if(!u)//一直循环到最大流的情况                break;            ans+=u;        }    }    return ans;}int main(){    while(~scanf("%d%d",&n,&m))    {        memset(mapp,0,sizeof(mapp));        for(int i=1;i<=n;i++)        {            int x,y,w;            scanf("%d%d%d",&x,&y,&w);            mapp[x][y]+=w;//防止有重边,表示之前根本不知道有可能有重边,卡了n久        }        bg=1,ed=m;        printf("%d\n",dinic());    }    return 0;}

比起大一划水,这段时间的学习效率已经算高了QAQ,嗯,继续保持。。。