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

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

题意:N个区域,每个区域有一个避难所,现在每个区域有一定数量的牛,避难所可以容纳一定数量的牛,下雨的时所有的牛都找到避难所所需要的时间,如果有的牛不能找到避难所,输出-1。用费用流是错的,一个错误犯多次,或许是改变思维不容易吧。

网络流

1.源点到区域间连线,权值为现在区域牛的数量,区域到汇点连线,权值为可以容纳的牛的数量

2.然后floyd求出所有的点间的距离,然后二分答案,距离小于等于mid值的,连线。。。但是如果在原来的区域间连线,就会WA,因为如果mid=1, 1->2为1  , 2->3为1,

1->3为2的话,1->3不应该连线,但是如果连了1->2,2->3,那么1到3也是连通的,所以建图时把每个区域拆点

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstring>
#define nMAX 1005
#define mMAX 210000
#define infl (long long)999999999*300
#define inf 1200
using namespace std;
int head[nMAX],has[nMAX],contain[nMAX],level[nMAX],qu[nMAX];
long long map[nMAX][nMAX],high,low,mid;
int n,s_edge,s,t;
struct Edge
{
    int u,v,cap,nxt;
}edge[mMAX];
long long maxl(long long a,long long b)
{
    return a>b?a:b;
}
long long minl(long long a,long long b)
{
    return a<b?a:b;
}
int min(int a,int b)
{
    return a<b?a:b;
}
void floyd()
{
    int i,j,k;
    for(k=1;k<=n;k++)
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
            {
                if(map[i][k]==infl||map[k][j]==infl)continue;
                map[i][j]=minl(map[i][j],map[i][k]+map[k][j]);
                high=maxl(high,map[i][j]);
            }
}
void addedge(int u,int v,int cap)
{
    s_edge++;
    edge[s_edge].v=v;
    edge[s_edge].cap=cap;
    edge[s_edge].nxt=head[u];
    head[u]=s_edge;

    s_edge++;
    edge[s_edge].v=u;
    edge[s_edge].cap=0;
    edge[s_edge].nxt=head[v];
    head[v]=s_edge;
}

int dfs(int x,int cap)
{
    if(x==t)return cap;
    int temp=cap;
    for(int e=head[x];e;e=edge[e].nxt)
    {
        int v=edge[e].v;
        if(level[v]==level[x]+1&&temp>0&&edge[e].cap>0)
        {
            int tt=dfs(v,min(temp,edge[e].cap));
            edge[e].cap-=tt;
            edge[e^1].cap+=tt;
            temp-=tt;
        }
    }
    return cap-temp;
}
bool bfs()
{
    int beg,tail;
    for(int i=0;i<=t;i++)level[i]=-1;
    //memset(level,-1,sizeof(level));
    beg=0,tail=1;
    qu[0]=0;
    level[0]=0;
    while(beg!=tail)
    {
        int u=qu[beg++];
        for(int e=head[u];e;e=edge[e].nxt)
        {
            int v=edge[e].v;
            if(level[v]==-1&&edge[e].cap>0)
            {
                level[v]=level[u]+1;
                qu[tail++]=v;
                if(tail==nMAX)tail=0;
            }
        }
        if(beg==nMAX)beg=0;
    }
    if(level[t]==-1)return 0;
    return 1;
}
int dinic()
{
    int SUM=0;
    while(bfs())
    {
        SUM+=dfs(0,inf);
    }
    return SUM;
}
int main()
{
    int x,y,i,j,p,num;
    long long w;
    while(~scanf("%d%d",&n,&p))
    {
        num=0;
        for(i=1;i<=n;i++)
        {
            scanf("%d%d",&has[i],&contain[i]);
            num+=has[i];
        }
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
            {
                if(i==j)map[i][j]=0;
                else map[i][j]=infl;
            }
        while(p--)
        {
           scanf("%d%d%lld",&x,&y,&w);
           map[y][x]=map[x][y]=minl(map[x][y],w);
        }
        low=0,high=0;
        floyd();
        long long tt=++high;
        while(high>low)
        {
            mid=(high+low)/2;
            memset(head,0,sizeof(head));
            s_edge=1;
            s=0,t=2*n+1;
            for(i=1;i<=n;i++)
            {
                addedge(s,i,has[i]);
                addedge(i+n,t,contain[i]);
            }
            for(i=1;i<=n;i++)
                for(j=1;j<=n;j++)
                {
                    if(map[i][j]<=mid&&contain[j]>0)
                    {
                        addedge(i,j+n,inf);
                    }
                }
            int a=dinic();
            if(a>=num)
            {
                high=mid;
            }
            else low=mid+1;
        }
        if(low==tt)printf("-1\n");
        else  printf("%lld\n",high);
    }
    return 0;
}

  

posted @ 2012-08-14 21:58  快乐.  阅读(210)  评论(0编辑  收藏  举报