POJ2391 Ombrophobic Bovines(二分+拆点+最大流)

来源:互联网 发布:php数据类型的意思 编辑:程序博客网 时间:2024/06/03 15:08

链接:http://poj.org/problem?id=2391
题意:
有n个点,m条边(无向边),先输入n个点的信息,前面那个是这个点内已经有的牛,后面的是这个点最多可以容纳几头牛。m条边就是起点,终点,所需时间。问:所有奶牛都在点内安排好,所需的最少时间。如果无解输出-1。
根据题意,我们会想到一个思路,就是二分最大距离,然后跑最大流,这是一个初级思路,我写了这个之后发现是错的,仔细思考以后发现这样一种情况。不同的点间接连接着,我们二分的最大距离是x的话,这些点的距离最大确实都不超过x,但是加起来却超过了x,这样不符合我们的要求。我看了别人的博客,学习到一个思路就是拆点。
把每个点拆成入点和出点两种。那么我们在建图的时候,可以这样建图。
源点->每个点的入点 权值为这个点已存在的牛。
每个点的出点->汇点 权值为这个点可以容纳的牛。
每个点的入点->自己的出点 权值为所有牛的总数,因为每条路可以容纳无数牛。
最关键的是点与点之间的路径怎么建立。我们的目的是为了避免间接相连,也就是说,每条路径存的都要是直达。从前面的边可以看出,从每个点的出点出去之后都是汇点,而且,每个点的入点都是从源点得到的。所以要直达的话,点之间的路径就是符合条件的边(u,v)的(u)入点->(v)出点。
知道这些条件以后,就是二分距离,然后最大流了。
这题还有一个地方需要注意,就是一开始在图中设置的距离的最大值的问题,我们考虑有200个点,每个点 i 只和i + 1相连,而且距离是最大值1e9,那么点 1 和点200的距离就是199*1e9,差不多200*1e9就是2e11。因为一开始最大值设置的不对,一直错没有发现原因。
Accepted 1708K 282MS G++ 2850B

#include<cstdio>#include<cstring>#include<string>#include<queue>#include<map>#include<iostream>#include<vector>#include<cstdlib>#include<cmath>#include<stack>#include<cctype>#include<set>#include<cassert>#include<algorithm>using namespace std;typedef long long ll;const int INF=1e9+7;typedef pair<int,int> pii;#define in(x) (x)#define out(x) (x+n)struct node{    int cow,last;}val[210];int n,m,Cow,st,ed;ll pic[210][210];void floyd(){    for(int k=1;k<=n;k++){        for(int i=1;i<=n;i++){            for(int j=1;j<=n;j++){                if(pic[i][j]>pic[i][k]+pic[k][j]){                    pic[i][j]=pic[i][k]+pic[k][j];                }            }        }    }}int F[410][410];int d[410];void build(ll v){    st=0;ed=n+n+1;    memset(F,0,sizeof F);    for(int i=1;i<=n;i++){        F[st][in(i)]=val[i].cow;        F[out(i)][ed]=val[i].last;        F[in(i)][out(i)]=Cow;    }    for(int i=1;i<=n;i++){        for(int j=1;j<=n;j++){            if(pic[i][j]<=v){                F[in(i)][out(j)]=Cow;            }        }    }}bool BFS(){    queue<int> Q;    memset(d,-1,sizeof d);    d[st]=0;Q.push(st);    while(!Q.empty()){        int s=Q.front();Q.pop();        for(int i=1;i<=ed;i++){            if(F[s][i]>0&&d[i]<0){                d[i]=d[s]+1;Q.push(i);            }        }    }    return d[ed]>0;}int DFS(int s,int t,int flow){    if(s==t||flow==0)return flow;    int ans=0;    for(int i=1;i<=ed;i++){        if(F[s][i]>0&&d[i]==d[s]+1){            int ff=DFS(i,t,min(flow,F[s][i]));            if(ff>0){                F[s][i]-=ff;                F[i][s]+=ff;                ans+=ff;                flow-=ff;                if(!flow)break;            }        }    }    if(!ans)d[s]=-1;    return ans;}int dinic(ll v){    build(v);    int ans=0;    while(BFS()){        ans+=DFS(st,ed,INF);    }    return ans;}int main(){//    freopen("D://input.txt","r",stdin);    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++){        scanf("%d%d",&val[i].cow,&val[i].last);        Cow+=val[i].cow;    }    for(int i=1;i<=n;i++){        for(int j=1;j<=n;j++){            if(i!=j)pic[i][j]=2e11;            else pic[i][j]=0;        }    }    for(int i=1;i<=m;i++){        int a,b,c;scanf("%d%d%d",&a,&b,&c);        if(pic[a][b]>c)pic[a][b]=pic[b][a]=c;    }    floyd();    ll l=0,r=0,ans=-1;    for(int i=1;i<=n;i++){        for(int j=1;j<=n;j++){            if(pic[i][j]!=2e11)                r=max(r,pic[i][j]);        }    }    while(l<=r){        ll m=(l+r)>>1;        if(dinic(m)==Cow){            ans=m;r=m-1;        }        else l=m+1;    }    printf("%I64d\n",ans);    return 0;}
0 0
原创粉丝点击