zoukankan      html  css  js  c++  java
  • POJ--2391--Ombrophobic Bovines【分割点+Floyd+Dinic优化+二分法答案】最大网络流量

    联系:http://poj.org/problem?id=2391

    题意:有f个草场,每一个草场当前有一定数目的牛在吃草,下雨时它能够让一定数量的牛在这里避雨,f个草场间有m条路连接,每头牛通过一条路从一点到还有一点有一定的时间花费,如今要下雨了,农场主发出警报牛就会马上去避雨。

    如今告诉每一个草场的情况。以及m条边的信息。农场主至少须要提前多久发出警报才干保证全部牛都能避雨?假设不是全部牛都能成功避雨输出-1。


    思路:这道题须要拆点,是看到魏神的博客才知道的。我们把原图拆成一个二分图,避免突破最大距离限制的情况,每一个点变成两个点,即i变为i‘和i’‘,建立一个源点连接每一个i’,容量为初始每一个草场牛的数目。建立一个汇点,全部的i‘’指向汇点,容量为每一个草场能容纳的牛的数目。假设两个点i和j连接。则在i’和j‘’以及j‘和i’‘之间建一条路径。容量为INF,能够走无限多的牛。然后这道题就和之前做的一道POJ2112一样了,POJ2112不用拆点,由于它本身就是一个二分图。

    接下来就是Floyd处理出随意两点间最短路径。然后二分答案。

    可是这道题还没有完,我套之前的Dinic模板,TLE了。这道题最大可能的边数比POJ2112大,而Case时限一样,我手写队列。还是TLE,我再把vis数组去掉用dist取代vis功能,还是TLE,我在网上搜AC的Dinic代码,看到一个和我的差点儿相同。粘贴交了一发。TLE,无力吐槽。。。

    找到了一个看上去有些修改的代码,依照它修改的地方改我自己的。219MS AC。

    我看了一下。我认为基本的优化地方是这样:

    1. 我之前的模板,是从源点起找遍每一条增广路进行松弛,优化算法是找到一条增广路松弛、退出,更新最大流值,再找下一条,直到更新值返回0说明已更新到头,避免了多余的搜索。

    2. 假设此时的顶点已不存在增广路,将它从当前的层次网络中删除。回溯后不会再搜。

    我认为这是两个优化到的地方,这么进行了优化之后效率提升非常明显!


    #include<cstring>
    #include<string>
    #include<fstream>
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    #include<queue>
    #include<map>
    #include<set>
    #include<vector>
    #include<stack>
    #include<ctime>
    #include<cstdlib>
    #include<functional>
    #include<cmath>
    using namespace std;
    #define PI acos(-1.0)
    #define MAXN 200100
    #define eps 1e-7
    #define INF 0x7FFFFFFF
    #define LLINF 0x7FFFFFFFFFFFFFFF
    #define seed 131
    #define mod 1000000007
    #define ll long long
    #define ull unsigned ll
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    struct node{
        int u,w,next;
    }edge[100010];
    int head[410],dist[410],q[410];
    int aa[410],bb[410];
    ll e[410][410];
    int n,m,cnt,src,sink,f,p;
    void add_edge(int a,int b,int c){
        edge[cnt].u = b;
        edge[cnt].w = c;
        edge[cnt].next = head[a];
        head[a] = cnt++;
    }
    void floyd(){
        int i,j,k;
        for(k=1;k<=f;k++){
            for(i=1;i<=f;i++){
                if(e[i][k]==LLINF)  continue;
                for(j=1;j<=f;j++){
                    if(e[i][k]+e[k][j]<e[i][j]&&e[i][k]!=LLINF&&e[k][j]!=LLINF)
                        e[i][j] = e[i][k] + e[k][j];
                }
            }
        }
    }
    void build_graph(ll minm){
        int i,j;
        cnt = 0;
        memset(head,-1,sizeof(head));
        for(i=1;i<=f;i++){
            add_edge(src,i,aa[i]);
            add_edge(i,src,0);
            add_edge(i+f,sink,bb[i]);
            add_edge(sink,i+f,0);
            for(j=1;j<=f;j++){
                if(e[i][j]<=minm){
                    add_edge(i,j+f,INF);
                    add_edge(j+f,i,0);
                }
            }
        }
    }
    bool bfs(){
        int i,j;
        memset(dist,-1,sizeof(dist));
        int f = 0, t = 1;
        q[0] = src;
        dist[src] = 1;
        while(f<t){
            int u = q[f++];
            for(i=head[u];i!=-1;i=edge[i].next){
                int v = edge[i].u;
                if(dist[v]==-1&&edge[i].w){
                    dist[v] = dist[u] + 1;
                    q[t++] = v;
                }
            }
        }
        if(dist[sink]!=-1)  return true;
        return false;
    }
    int dfs(int u,int delta){
        int i,j;
        int dd;
        if(u==sink) return delta;
        for(i=head[u];i!=-1;i=edge[i].next){
            if(dist[edge[i].u]==dist[u]+1&&edge[i].w&&(dd = dfs(edge[i].u,min(delta,edge[i].w)))){
                edge[i].w -= dd;
                edge[i^1].w += dd;
                return dd;
            }
        }
        dist[u] = -1;
        return 0;
    }
    int main(){
        int i,j;
        int ta,tb,tc;
        int cow;
        scanf("%d%d",&f,&p);
        n = 2 * f + 2;
        src = 0;
        sink = 2 * f + 1;
        cow = 0;
        for(i=1;i<=f;i++){
            scanf("%d%d",&aa[i],&bb[i]);
            cow += aa[i];
        }
        for(i=0;i<=f;i++){
            for(j=0;j<=f;j++)
                e[i][j] = LLINF;
            e[i][i] = 0;
        }
        for(i=0;i<p;i++){
            scanf("%d%d%d",&ta,&tb,&tc);
            if(tc<e[ta][tb])    e[ta][tb] = e[tb][ta] = tc;
        }
        floyd();
        ll mid,l = 0,r = 0;
        for(i=1;i<=f;i++){
            for(j=1;j<=f;j++){
                if(e[i][j]!=LLINF)  r = max(e[i][j],r);
            }
        }
        int sum;
        ll ans = -1;
        while(l<=r){
            mid = (l+r)>>1LL;
            //cout<<l<<" "<<r<<endl;
            sum = 0;
            build_graph(mid);
            while(bfs()){
                while(1){
                    int ttt = dfs(src,INF);
                    if(!ttt)    break;
                    sum += ttt;
                }
            }
            if(sum==cow){
                ans = mid;
                r = mid-1;
            }
            else    l = mid + 1;
        }
        printf("%I64d
    ",ans);
        return 0;
    }



    版权声明:本文博主原创文章。博客,未经同意不得转载。

  • 相关阅读:
    国外名校课程视频爆红 网友总结“必杀技”(图)
    设置mysql密码
    Writing Linux LCD drivers—深入分析framebuffer设备驱动的结构
    LAMP架构中,php 与 php、php与C语言程序等 之间 的网络通信 问题
    API & ABI
    Linux 6初体验:桌面性能堪比新版Ubuntu
    diff 比较两个文件夹
    11种错误的保养皮肤习惯
    服务器领域Linux击败Windows的5大理由
    CentOS5.5 FTP安装配置
  • 原文地址:https://www.cnblogs.com/yxwkf/p/4799993.html
Copyright © 2011-2022 走看看