POJ 2391 Ombrophobic Bovines (最大流+二分答案)

来源:互联网 发布:java 读取jar中的文件 编辑:程序博客网 时间:2024/05/20 06:51

题意:有F个牧场,每个牧场当前牛的头数为num,牧场能容纳的牛的头数为rong,牧场与牧场间有P条边,距离为dis,现在所有的牛同时出发,问所有牛到达可容纳的牧场,最短的时间。1=<F<=200,1<=P<=1500,0<=num<=1000,0<=rong<=1000,1<=dis<=10^9

分析:把每个点拆成两个点(i,i‘'),那么设源点为S=0,汇点为T=2F+1。连边add(S,i,numi),add(i'',T,rongi)。

由于牛是同时出发,求的是最少时间,所以不是费用流。

那么只有二分答案了,每次都新建图再跑最大流,时间复杂度比最大流多了log(INF*INF)≈64,找到一个time,所有小于这个time的边都要加入图中,然后跑最大流,如果最大流等于所有牛的头数,那么这个time是满足的,在找比time小的时间,若不满足则找比time大的时间。

#include<iostream>#include<string>#include<stdio.h>#include<string.h>#include<vector>#include<math.h>#include<queue>#include<map>#include<set>#include<algorithm>using namespace std;#define MAXN 10000#define MAXM 100010#define LL long long#define INF 0x3f7f7f7fconst double eps = 1e-10;struct Edge{    int from,to,cap,flow;    Edge(int from=0,int to=0,int cap=0,int flow=0):from(from),to(to),cap(cap),flow(flow){}};int S,T;vector<Edge>edges;vector<int>g[MAXN];int vis[MAXN],d[MAXN],cur[MAXN];void init(){    for(int i=0;i<MAXN;i++)        g[i].clear();    edges.clear();}void add(int from,int to,int cap){    edges.push_back(Edge(from,to,cap,0));    edges.push_back(Edge(to,from,0,0));    int m=edges.size();    g[from].push_back(m-2);    g[to].push_back(m-1);}bool bfs(){    memset(vis,0,sizeof(vis));    d[S]=0;    queue<int>q;    q.push(S);    vis[S]=1;    while(!q.empty())    {        int x=q.front();        q.pop();        int sz=g[x].size();        for(int i=0;i<sz;i++)        {            Edge &e=edges[g[x][i]];            if(!vis[e.to]&&e.cap>e.flow)            {                vis[e.to]=1;                d[e.to]=d[x]+1;                q.push(e.to);            }        }    }    return vis[T];}int dfs(int x,int a){    if(x==T||a==0)        return a;    int flow=0,f;    int sz=g[x].size();    for(int &i=cur[x];i<sz;i++)    {        Edge &e=edges[g[x][i]];        if(d[x]+1==d[e.to])        {           f=dfs(e.to,min(a,e.cap-e.flow));           if(f>0)           {               e.flow+=f;               edges[g[x][i]^1].flow-=f;               flow+=f;               a-=f;               if(a==0)break;           }        }    }    return flow;}int F,P,num,rong;LL dis[401][401];LL max(LL x,LL y){    return x>y?x:y;}LL min(LL x,LL y){    return x<y?x:y;}struct Cow{    int num,rong;}cow[MAXN];void floyd(){    int i,j,k;    for(k=1;k<=F;k++)    {        for(i=1;i<=F;i++)        {            for(j=1;j<=F;j++)            {                if(dis[i][j]>dis[i][k]+dis[k][j])                   dis[i][j]=dis[i][k]+dis[k][j];            }        }    }}int maxFlow(){    int flow=0;    while(bfs())    {        memset(cur,0,sizeof(cur));        flow+=dfs(S,INF);    }    return flow;}void solve(){     floyd();     int i,j;     S=0,T=2*F+1;/***********************************/     LL l=0,r=(LL)INF*(LL)INF;     LL ans=(LL)INF*(LL)INF;     while(l<r)     {         LL mid=(l+r)>>1;         init();        for(i=1;i<=F;i++)        {         add(0,i,cow[i].num);//源点到i加边,容量为num         add(i+F,2*F+1,cow[i].rong);//i拆出来的点到汇点加边,容量为rong        }        LL maxx=0;        for(i=1;i<=F;i++)        {            for(j=1;j<=F;j++)            {                if(dis[i][j]<=mid)//枚举到mid,mid以下的dis都要add                {                    add(i,j+F,INF);                    maxx=max(maxx,dis[i][j]);                }            }        }        int cnt=maxFlow();        if(cnt==num)//如果枚举到mid的时候,最大流任然为最大值,那么mid是可行的        {            r=mid;            ans=min(ans,maxx);        }        else l=mid+1;     }/****************************************/     if(ans==(LL)INF*(LL)INF)        puts("-1");     else     printf("%lld\n",ans);}int main(){    int i,j;    while(scanf("%d%d",&F,&P)!=EOF)    {        num=rong=0;        for(i=0;i<301;i++)        {            for(j=0;j<301;j++)            {                if(i==j)                    dis[i][j]=0;                else                {                    dis[i][j]=(LL)INF*(LL)INF;                }            }        }        for(i=1;i<=F;i++)        {            scanf("%d%d",&cow[i].num,&cow[i].rong);            num+=cow[i].num;            rong+=cow[i].rong;        }        for(i=1;i<=P;i++)        {            int u,v;            LL len;            scanf("%d%d%lld",&u,&v,&len);            dis[u][v]=dis[v][u]=min(len,dis[u][v]);        }        solve();    }    return 0;}


0 0
原创粉丝点击