POJ 2391 Ombrophobic Bovines【二分+最大流】

题意: 已知有 N 个牛棚,且每个牛棚在一开始的时候有一定数量的牛,每个牛棚可以用来让牛避雨,但容量都有一定的限制,知道了一些牛棚之间的道路长度,

         问使得下雨时使所有牛都可以找到地方躲雨,且要使得所有牛中走过的路中的最大值尽可能小,并求出该最大值

分析: 建图:

          将每个牛棚拆成两个点v,v`

          建立一个源点 s =0 ,        在 s 和每个点 i 之间连一条容量大小为该牛棚初始牛数量的边,

          建立一个汇点 t =2*n+1     在 每个点 i+n 和 t 之间连一条容量大小为该牛棚容量的边。

          如果点 u 和 v 满足条件,就在 u 和 v +n ,v 和 u+n之间连一条容量大小为 INF 的边。

          如果最大流 = 牛的数量 ,即说明该情况符合。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define clr(x)memset(x,0,sizeof(x))
#define INF 0x1f1f1f1f
#define min(a,b)(a)<(b)?(a):(b)
int v[405][405];
int gap[405];
int dis[405];
int c[405][405];
void init(int s,int u,int n)
{
    int v,x,front=0,rear=0;
    int q[405];
    clr(gap);
    memset(dis,0xff,sizeof(dis));
    q[rear++]=u;
    dis[u]=0;
    while(front<rear)
    {
        x=q[front++];
        gap[dis[x]]++;
        for(v=0;v<=n;v++)
            if(dis[v]==-1&&c[v][x]>0)
            {
                dis[v]=dis[x]+1;
                q[rear++]=v;
            }
    }
}
int sap(int s,int u,int n)
{
    init(s,u,n);
    int flag,flow=0,top=s,i,j,k;
    int pre[405];
    int low[405];
    while(dis[s]<=n)
    {
        flag=0;
        low[s]=INF;
        for(i=0;i<=n;i++)
            if(c[top][i]>0&&dis[top]==dis[i]+1&&dis[i]>=0)
            {
                flag=1;
                break;
            }
        if(flag)
        {
            low[i]=c[top][i];
            low[i]=min(low[i],low[top]);
            pre[i]=top;
            top=i;
            if(top==u)
            {
                flow+=low[u];
                j=top;
                while(j!=s)
                {
                    k=pre[j];
                    c[k][j]-=low[u];
                    c[j][k]+=low[u];
                    j=k;
                }
                top=s;
                clr(low);
            }
        }
        else
        {
            int dmin=n;
            for(j=0;j<=n;j++)
                if(c[top][j]>0&&dis[j]+1<dmin&&dis[j]>=0)
                    dmin=dis[j]+1;
            gap[dis[top]]--;
            if(gap[dis[top]]==0)
                break;
            gap[dmin]++;
            dis[top]=dmin;
            if(top!=s)
                top=pre[top];
        }
    }
    return flow;
}
long long g[405][405];
int st[202];
int ho[202];
int ok(long long ti,int s,int n,int tot)
{
    int i,j,flow;
    clr(c);
    for(i=1;i<=n;i++)
    {
        c[s][i]=st[i];
        c[i+n][n*2+1]=ho[i];
    }
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            if(g[i][j]!=-1&&g[i][j]<=ti)
            {
                c[i][j+n]=INF;
                c[j][i+n]=INF;
            }
    flow=sap(s,2*n+1,2*n+1);
    if(flow==tot)
        return 1;
    return 0;
}
int main()
{
    int s,t,n,m,i,j,k,a,b,t1,t2;
    long long low,high,mid,res,w;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        s=0;
        t1=t2=0;
        high=0;
        for(i=1;i<=n;i++)
        {
            scanf("%d%d",&st[i],&ho[i]);
            t1+=st[i];
            t2+=ho[i];
        }
        memset(g,-1,sizeof(g));
        while(m--)
        {
            scanf("%d%d%lld",&a,&b,&w);
            if(g[a][b]==-1||w<g[a][b])
            {
                //high+=w;
                g[a][b]=g[b][a]=w;
            }
        }
        if(t1>t2)
        {
            printf("-1\n");
            continue;
        }
        for(k=1;k<=n;k++)
            for(i=1;i<=n;i++)
                if(g[i][k]!=-1)
                    for(j=1;j<=n;j++)
                        if(g[k][j]!=-1&&(g[i][k]+g[k][j]<g[i][j]||g[i][j]==-1))
                            g[i][j]=g[i][k]+g[k][j];
        for(i=1;i<=n;i++)
            g[i][i]=0;
        low=0;
        high=0;
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
                if(g[i][j]>high)
                    high=g[i][j];
        res=-1;
        while(low<=high)
        {
            mid=(low+high)>>1;
            if(ok(mid,s,n,t1))
            {
                res=mid;
                high=mid-1;
            }
            else
                low=mid+1;
        }
        printf("%lld\n",res);
    }
    return 0;
}

 

posted @ 2012-08-14 17:10  'wind  阅读(206)  评论(0编辑  收藏  举报