网络流_poj1273

暑假培训,前几天没老师讲,自己在机房看资料,偶然发现网络流的算法,看来两天,不知所云,说的云里雾里的。

网上找资料,大多用C++写的,后来发现一大牛的代码。看来半天,豁然开朗,大牛就是大牛。代码相当规范、简练。唉。。。。

题目链接:http://poj.org/problem?id=1273


Drainage Ditches
Time Limit: 1000MS
Memory Limit: 10000K
Total Submissions: 55336
Accepted: 21139

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
 
题目大意:下雨的时候约翰的田里总是积水,积水把他种的三叶草给淹了,他于是做了若干排水沟,每条沟在起始处安置一个阀门来控制这条沟的最大排水量,现在给出沟的条数以及阀门的个数。并给出每条沟的最大排水量。约翰的田里的积水处是阀门1,排出水的位置是最后一个阀门。求约翰在处理积水时的最大排出量。





   代码运行情况:如图(第一次写博客,图在下面,将就着看吧)
   图片不知怎么的传不上来,写在这吧   : Accept     628k    0(16)MS    C     1869B       第一次提交0ms  之后一直16ms
   参考的资料:http://pan.baidu.com/s/1nt5bngX

代码:


#include <stdio.h>
#include <string.h>
struct Map
{
 int f;//反向
 int c;//正向
}map[250][250];//储存图 
int pre[250];  //储存前驱点
int q[250*250]; //广度搜索用的队列
int v[250];     //记录点对应的流量
int N,M,s,t;

int Abs(int x)//求绝对值  貌似写成abs编译不过
{
    return x>0?x:-x;
}

int min(int x,int y)//求最小值
{
     return x<y?x:y;
}

void set()//初始化  输入
{
    int i,a,b,c;
    memset(map,0,sizeof(map));
    for(i=0;i<N;i++)
    {
        scanf("%d%d%d",&a,&b,&c);
        map[a][b].c+=c;
    }
}

void solve()
{
    int i,j;
    int head,tail,ans;//队列的头尾指针
    s=1;
    t=M;
    while(1) //寻找 所有从源点到汇点的路径
    {
        memset(pre,0,sizeof(pre));
        head=0,tail=1;
        q[0]=s;  //源点入队
        v[s]=1000000000;//源点可供应的流量假定无限大 (给定一个足够大的值)
        pre[s]=s;//源点的前驱为其本身
        while(head<tail&&pre[t]==0)
		/*寻找单条从源点到汇点的路径(队首小于队尾 队列未访问到底 pre[t]==0汇点前驱为0  即汇点未被访问到)*/
        {
            i=q[head];    //i为当前已发现的点
            for(j=1;j<=M;j++)//添加所有与head点相连的点 到队列
            {
                if(!pre[j])  //当前点没被利用
                {
                    if(map[i][j].f<map[i][j].c)//当前路径还能提供流量   map[i][j].f==map[i][j].c==0 此路不通
                    {
                        pre[j]=i;//记录当前点的前驱
                        q[tail++]=j;//入队
                        v[j]=min(v[i],map[i][j].c-map[i][j].f);//比较  记录最大流
                    }
                    else if(map[j][i].f>0)
                    {
                        pre[j]=-i;
                        q[tail++]=j;
                        v[j]=min(v[i],map[j][i].f);
                    }
                }
            }
            head++;//出队  其实我一直感觉 写成循环队列会好些
        }
        if(pre[t]==0)break;//没有前驱点 即没找到  所有的可行路径均已被发现
        i=t;
        while(i!=s)//回朔 计算该路的流量  添加反向路径 并修改流量
         {
            j=Abs(pre[i]);
            if(pre[i]>0)map[j][i].f+=v[t];//此为正向
            else map[i][j].f-=v[t];//反向路径
            i=j;
        }
    }
    ans=0;
    for(i=1;i<=M;i++)ans+=map[s][i].f;//计算总流量
    printf("%d\n",ans);
}

int main()
{
    while(~scanf("%d%d",&N,&M))
    {
        set();
        solve();
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值