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\n",ans);
    return 0;
}

POJ--2391--Ombrophobic Bovines【拆点+Floyd+Dinic优化+二分答案】网络最大流

时间: 2024-08-08 17:49:20

POJ--2391--Ombrophobic Bovines【拆点+Floyd+Dinic优化+二分答案】网络最大流的相关文章

POJ--2391--Ombrophobic Bovines【分割点+Floyd+Dinic优化+二分法答案】最大网络流量

联系:http://poj.org/problem?id=2391 题意:有f个草场,每一个草场当前有一定数目的牛在吃草,下雨时它能够让一定数量的牛在这里避雨,f个草场间有m条路连接,每头牛通过一条路从一点到还有一点有一定的时间花费,如今要下雨了,农场主发出警报牛就会马上去避雨. 如今告诉每一个草场的情况.以及m条边的信息.农场主至少须要提前多久发出警报才干保证全部牛都能避雨?假设不是全部牛都能成功避雨输出-1. 思路:这道题须要拆点,是看到魏神的博客才知道的.我们把原图拆成一个二分图,避免突破

poj 2391 Ombrophobic Bovines, 最大流, 拆点, 二分, dinic

poj 2391 Ombrophobic Bovines, 最大流, 拆点, 二分 dinic /* * Author: yew1eb * Created Time: 2014年10月31日 星期五 15时39分22秒 * File Name: poj2391.cpp */ #include <ctime> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring&g

POJ 2391 Ombrophobic Bovines 不喜欢雨的奶牛 Floyd+二分枚举+最大流

题目链接:POJ 2391 Ombrophobic Bovines Ombrophobic Bovines Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 15006   Accepted: 3278 Description FJ's cows really hate getting wet so much that the mere thought of getting caught in the rain makes

Poj 2391 Ombrophobic Bovines 网络流 拆点

Poj 2391 Ombrophobic Bovines 网络流 拆点 FJ's cows really hate getting wet so much that the mere thought of getting caught in the rain makes them shake in their hooves. They have decided to put a rain siren on the farm to let them know when rain is approa

POJ 2391 Ombrophobic Bovines (二分 + floyd + 网络流)

POJ 2391 Ombrophobic Bovines 链接:http://poj.org/problem?id=2391 题目:农场有F 块草地,1≤F≤200,奶牛们在草地上吃草.这些草地之间有P 条路相连,1≤P≤1500,这些路足够宽,再多的奶牛也能同时在路上行走.有些草地上有避雨点,奶牛们可以在此避雨.避雨点的容量是有限的,所以一个避雨点不可能容纳下所有的奶牛.草地与路相比很小,奶牛们通过时不需要花费时间.计算警报至少需要提前多少时间拉响,以保证所有的奶牛都能到达一个避雨点. 思路:

POJ 2391 Ombrophobic Bovines(最大流+拆点)

POJ 2391 Ombrophobic Bovines 题目链接 题意:一些牛棚,有a只牛,现在下雨,每个牛棚容量量变成b,现在有一些道路连接了牛棚,问下雨后牛走到其他牛棚,使得所有牛都有地方躲雨,最后一只牛要走多久 思路:二分答案,然后最大流去判断,建图的方式为,牛棚拆点,源点连向入点,容量为a,出点连向汇点容量为b,中间入点和出点之间根据二分的值判断哪些边是可以加入的 代码: #include <cstdio> #include <cstring> #include <

POJ 2391 Ombrophobic Bovines (二分,最短路径,网络流sap,dinic,预留推进 )

Ombrophobic Bovines Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14019   Accepted: 3068 Description FJ's cows really hate getting wet so much that the mere thought of getting caught in the rain makes them shake in their hooves. They h

poj 2391 Ombrophobic Bovines(最大流+floyd+二分)

Ombrophobic Bovines Time Limit: 1000MSMemory Limit: 65536K Total Submissions: 14519Accepted: 3170 Description FJ's cows really hate getting wet so much that the mere thought of getting caught in the rain makes them shake in their hooves. They have de

POJ 2391 Ombrophobic Bovines

Ombrophobic Bovines Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 18623   Accepted: 4057 Description FJ's cows really hate getting wet so much that the mere thought of getting caught in the rain makes them shake in their hooves. They h