zoukankan      html  css  js  c++  java
  • POJ1273:Drainage Ditches——题解

    http://poj.org/problem?id=1273

    题目大意:

    n点m边网络流,求1-n最大流。

    ——————————————

    网络流板子,切了。

    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn=201;
    const int INF=2147483640;
    inline int read(){
        int X=0,w=0;char ch=0;
        while(ch<'0'||ch>'9'){w|=ch=='-';ch=getchar();}
        while(ch>='0'&&ch<='9')X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    struct node{
        int next;
        int to;
        int w;
    }edge[2*maxn];
    int head[2*maxn],cnt=-1;
    void add(int u,int v,int w){//u起点v终点w容量 
        cnt++;
        edge[cnt].to=v;
        edge[cnt].w=w;
        edge[cnt].next=head[u];
        head[u]=cnt;
        return;
    }
    int lev[maxn],cur[maxn];//lev层数,cur[i]为以i为起点的边的编号 
    bool bfs(int m){//强制1为源点,m为汇点 
        int dui[m],r=0;//队列和右指针 
        for(int i=1;i<=m;i++){//初始化 
            lev[i]=-1;
            cur[i]=head[i];
        }
        dui[0]=1,lev[1]=0;
        int u,v;//u起点v终点 
        for(int l=0;l<=r;l++){//左指针 
            u=dui[l];
            for(int e=head[u];e!=-1;e=edge[e].next){
                v=edge[e].to;
                if(edge[e].w>0&&lev[v]==-1){//1.能走 2.未分层 
                    lev[v]=lev[u]+1;
                    r++;
                    dui[r]=v;//v入队 
                    if(v==m)return 1;//分层完毕 
                }
            }
        }
        return 0;//无法分层 
    }
    int dinic(int u,int flow,int m){//u当前点,flow为下面的点能够分配多大的流量,m终点 
        if(u==m)return flow;//终点直接全流入
        int res=0,delta;//res实际流量 
        for(int &e=cur[u];e!=-1;e=edge[e].next){//'&'相当于cur[u]=e;即流满的边不会再被扫一次 
            int v=edge[e].to;
            if(edge[e].w>0&&lev[u]<lev[v]){//只能从低层往高层流 
                delta=dinic(v,min(edge[e].w,flow-res),m); 
                if(delta>0){//如果增广 
                    edge[e].w-=delta;//正向边容量减少 
                    edge[e^1].w+=delta;//反向边仍量增加(暗示退流) 
                    res+=delta;//扩张流量增加 
                    if(res==flow)break;//可流的都流完了,及时跳出 
                }
            }
        }
        if(res!=flow)lev[u]=-1;//没流完,说明以后不能从这个点流出任何流量,那就不需要这个点了 
        return res;
    }
    int main(){
        int n,m;
        while(scanf("%d%d",&n,&m)!=EOF){
        cnt=-1;
        memset(head,-1,sizeof(head));
        for(int i=1;i<=n;i++){
            int s=read();
            int e=read();
            int c=read();
            add(s,e,c);
            add(e,s,0);
        }
        int ans=0;
        while(bfs(m)==1)ans+=dinic(1,INF,m);
        printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Vmware安装CentOS6
    MySQL Explain详解
    数据库——Redis超详细总结
    读书——你的见识决定你的人生
    软件——Ubuntu16.04设置静态ip地址
    软件——Hexo-NexT配置个人博客
    Java——Java实现生产者消费者
    程序员的踩坑经验总结(四):死锁
    程序员的踩坑经验总结(三):内存泄露
    认识自己和世界
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/7930700.html
Copyright © 2011-2022 走看看