码迷,mamicode.com
首页 > 其他好文 > 详细

POJ2391.Ombrophobic Bovines(不喜欢雨的奶牛)——floyd+二分+拆点+最大流

时间:2015-02-18 18:48:33      阅读:215      评论:0      收藏:0      [点我收藏+]

标签:

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

写的挫的最大流会超时~~~

题目描述:
Jack 农场主的奶牛实在是太讨厌被淋湿了。决定在农场设置降雨警报,这样在快要下
雨的时候可以让奶牛们都知道。他们设置设计了一个下雨撤退计划,这样在下雨之前每头奶牛都
能躲到避雨点。然而,天气预报并不总是准确的。为了使得错误的天气预报影响尽可能小,他们
希望尽可能晚地拉响警报,只要保证留有足够的时间让所有的奶牛都能回到避雨点就可以了。
农场有F 块草地,1≤F≤200,奶牛们在草地上吃草。这些草地之间有P 条路相连,1≤P≤
1500,这些路足够宽,再多的奶牛也能同时在路上行走。
有些草地上有避雨点,奶牛们可以在此避雨。避雨点的容量是有限的,所以一个避雨点不可
能容纳下所有的奶牛。草地与路相比很小,奶牛们通过时不需要花费时间。
计算警报至少需要提前多少时间拉响,以保证所有的奶牛都能到达一个避雨点。

输入描述:
测试数据的格式如下:
(1) 第1 行为两个整数,F 和P。
(2) 第2~F+1 行,每行为两个整数,描述了一块草地,前一个整数(范围为0~1000),表
示在该草地吃草的奶牛数量;后一个整数(范围为0~1000)该草地的避雨点能容纳的奶牛数量。
(3) 第F+2~F+P+1 行,每行有3 个整数,描述了一条路,第1 个和第2 个整数(范围为1~
F)为这条路连接的两块草地序号,第3 个整数(范围为0~1000,000,000),表示任何一头奶牛
通过这条路是需要花费的时间。

输出描述:
输出所有奶牛回到避雨点所需的最少时间,如果不能保证所有的奶牛都回到一个避雨点,则
输出”-1”。

**每个点拆成两个点,点i拆成i和i+n,i和i+n连边为无穷。则源点到i连边的容量为初始的奶牛数,i+n到汇点的连边为避雨点所能容纳的奶牛数,如果点i,j之间右边,则i到j+n的连边容量为无穷。
因为要求时间最少,所以是路径最短,先用floyd求得任意两点之间的最短路,牛转移的方法是同时的,不是一堆一堆转移的,所以二分枚举最小的边使得满流,就是所要求的答案**

新技能get
2060K 329MS C++ 3800B

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#define ll long long
#define inf ((ll)1<<38)
const int maxn= 405;//最大顶点数
const int maxm = 160005;//最大边数
const int INF=0x3f3f3f3f;
using namespace std;
int n,s,t,N;//输入的顶点数,源点,汇点,建图后的总顶点数(判断dis[s]<N)
struct node
{
    int to,cap,next,pre;//pre是指互为反向弧
}edges[maxm];
int head[maxn],tot,que[maxn],d[maxn],gap[maxn],cur[maxn],rpath[maxn];
//邻接表,边数,队列,距离标号,间隙优化,当前弧,可增广路上的弧编号
void init(){
    tot=0;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int c)
{
    edges[tot].to=v;
    edges[tot].cap=c;
    edges[tot].next=head[u];
    head[u] = tot ++;
    edges[tot-1].pre=tot;
    edges[tot].pre = tot-1;
    edges[tot].cap = 0;
    edges[tot].to = u;
    edges[tot].next = head[v];
    head[v] = tot ++;
}

void re_Bfs(){
    memset(gap,0,sizeof(gap));
    memset(d,-1,sizeof(d));
    int i,front=0,rear=0;
    que[rear ++] = t;
    gap[0] = 1;
    d[t] = 0;
    while(front != rear){
        int u = que[front ++];
        for(i = head[u];i != -1;i = edges[i].next){
            if(edges[edges[i].pre].cap == 0 || d[edges[i].to]!=-1)
                continue;
            d[edges[i].to] = d[u] + 1;
            gap[d[edges[i].to]] ++;
            que[rear ++] = edges[i].to;
        }
    }
}
int ISAP(){
    memset(gap,0,sizeof(gap));
    memset(d,0,sizeof(d));
    memcpy(cur,head,sizeof(head));
    int i,u=s,maxflow = 0;
    while(d[s] < N){
        if(u == t){
            int curflow = INF;
            for(i = s;i != t;i = edges[cur[i]].to)
                curflow = min(curflow,edges[cur[i]].cap);
            for(i = s;i != t;i = edges[cur[i]].to){
                edges[cur[i]].cap -= curflow;
                edges[edges[cur[i]].pre].cap += curflow;
            }
            maxflow += curflow;
            u = s;
        }
        for(i = cur[u];i != -1;i = edges[i].next)
            if(edges[i].cap > 0 && d[edges[i].to] + 1 == d[u])
                break;
        if(i != -1){
            cur[u] = i;
            rpath[edges[i].to] = edges[i].pre;
            u = edges[i].to;
        }
        else{
            if((-- gap[d[u]]) == 0) break;
            cur[u] = head[u];
            int Min = N;
            for(i = cur[u];i != -1;i = edges[i].next)
                if(edges[i].cap > 0)
                    Min = min(Min,d[edges[i].to]);
            gap[d[u]=Min+1] ++;
            if(u != s) u = edges[rpath[u]].to;
        }
    }
    return maxflow;
}
int cow[maxn],cury[maxn],sum,m;
ll dist[maxn][maxn];
void Build_Graph(ll mid){
    init();
    for(int i=1;i<=n;++i){
        addedge(s,i,cow[i]);
        addedge(i,i+n,INF);
        addedge(i+n,t,cury[i]);
        for(int j=1;j<=n;++j){
            if(dist[i][j]<=mid)
                addedge(i,j+n,INF);
        }
    }
}
void floyd(){
    for(int k=1;k<=n;++k){
        for(int i=1;i<=n;++i){
            for(int j=1;j<=n;++j)
                if(dist[i][k]<inf&&dist[k][j]<inf)
                dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
        }
    }
}
void solve(){
    ll l=1,r=inf-1,mid,ans=-1;
    s=0,t=n+n+1,N=n+n+2;
    while(l<r){
        mid=(l+r)>>1;
        Build_Graph(mid);
        int tmp=ISAP();
        if(tmp==sum) ans=mid;
        if(tmp>=sum) r=mid;
        else l=mid+1;
    }
    printf("%I64d\n",ans);
}
void Init(){
    sum=0;
    int u,v;ll w;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) dist[i][j]=inf;
    for(int i=1;i<=n;++i){
        scanf("%d%d",&cow[i],&cury[i]);
        sum+=cow[i];
    }
    while(m--){
        scanf("%d%d%I64d",&u,&v,&w);
        dist[u][v]=dist[v][u]=min(w,dist[u][v]);
    }
    floyd();
}
int main()
{
    Init();
    solve();
    return 0;
}

POJ2391.Ombrophobic Bovines(不喜欢雨的奶牛)——floyd+二分+拆点+最大流

标签:

原文地址:http://blog.csdn.net/u014141559/article/details/43877461

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!