poj2391 最大流+拆点

题意:F块草坪,上面有n头牛,可以容纳m个牛遮雨。将草坪一份为2,成为二部图。

对于此题,和poj2112很像,只是2112很明显的二部图。这道题就开始敲,但是建图遇到问题,草坪的2个值怎么处理,于是将1个草坪分成2分,一份与源点相连,值为牛的个数,

另一份与汇点相连表示可以留下多少牛,由于是一个草坪,所以这两份之间相连,容量无穷大。然后对于能够相通的2块草坪,由当前块草坪左边部分,向相连的连(前提时间小于二分的时间),容量无穷。二分答案。

#include<stdio.h>
#include<string.h>
#include<queue>
#define maxn 600
#define INF 10000000000000
#define LL __int64
using namespace std;
int vis[maxn],n,m,c[maxn],f[maxn],fn;
LL map[maxn][maxn],dis[maxn][maxn];
LL min(LL x,LL y)
{return x<y?x:y;}
LL max(LL x,LL y)
{return x>y?x:y;}
void init()
{
    int i,j;
    for(i=1;i<=fn;i++)
    {
        for(j=1;j<=fn;j++)
        {
            if(i==j)
                dis[i][j]=0;
            else
                dis[i][j]=INF;
        }
    }
}
void floyd()
{
    int i,j,k;
    for(k=1;k<=fn;k++)
        for(i=1;i<=fn;i++)
            for(j=1;j<=fn;j++)
            {
                if(dis[i][j]>dis[i][k]+dis[k][j])
                    dis[i][j]=dis[i][k]+dis[k][j];
            }
    /*for(i=1;i<=fn;i++)
    {
        for(j=1;j<=fn;j++)
        {
            printf("%d ",dis[i][j]);
        }
        printf("\n");
    }*/
}
void makemap(LL maxval)
{
    int i,j;
    memset(map,0,sizeof(map));
    for(i=1;i<=fn;i++)
    {
        map[0][i]=c[i];
    }
    for(i=1;i<=fn;i++)
        map[i+fn][n+1]=f[i];
    for(i=1;i<=fn;i++)
        map[i][i+fn]=INF;
    for(i=1;i<=fn;i++)
    {
        for(j=1;j<=fn;j++)
        {
            if(i==j)
                continue;
            if(dis[i][j]<=maxval)
            {
                map[i][j+fn]=INF;
            }
        }
    }
    /*for(i=0;i<=n+1;i++)
    {
        for(j=0;j<=n+1;j++)
        {
            printf("%d ",map[i][j]);
        }
        printf("\n");
    }*/
}
int BFS()
{
    int i,j;
    queue<int>q;
    memset(vis,-1,sizeof(vis));
    vis[0]=0;
    q.push(0);
    while(!q.empty())
    {
        int t=q.front();
        q.pop();
        for(i=0;i<=n+1;i++)
        {
            if(vis[i]<0&&map[t][i])
            {
                vis[i]=vis[t]+1;
                q.push(i);
            }
        }
    }
    if(vis[n+1]>0)
        return 1;
    return 0;
}
LL dfs(int u,LL low)
{
    int i,j;
    LL a;
    if(u==n+1)
        return low;
    for(i=0;i<=n+1;i++)
    {
        if(vis[i]==vis[u]+1&&map[u][i])
        {
            a=(LL)dfs(i,min(low,map[u][i]));
            if(!a)continue;
            map[u][i]-=a;
            map[i][u]+=a;
            return a;
        }
    }
    return 0;
}
int main()
{
    int i,j,num;
    LL maxval;
    while(scanf("%d%d",&fn,&m)!=EOF)
    {
        num=0;
        maxval=0;
        for(i=1;i<=fn;i++)
        {
            scanf("%d%d",&c[i],&f[i]);
            num+=c[i];
        }
        n=fn*2;
        init();
        for(i=0;i<m;i++)
        {
            LL x,y,z;
            scanf("%I64d %I64d %I64d",&x,&y,&z);
            if(dis[x][y]>z)
            {
                dis[y][x]=z;
                dis[x][y]=z;
            }
        }
        floyd();
        for(i=1;i<=fn;i++)
        {
            for(j=1;j<=fn;j++)
            {
                if(dis[i][j]!=INF)
                    maxval=max(maxval,dis[i][j]);
            }
        }
        LL l=0,r=maxval,ans=-1;
        while(l<=r)
        {
            LL ret=0;
            LL mid=(l+r)/2;
            makemap(mid);
            while(BFS())
            {
                while(1)
                {
                    LL a=dfs(0,INF);
                    if(!a)break;
                    ret+=a;
                }
            }
            //printf("%d ",mid);
            if(ret>=num)
            {
                ans=mid;
                r=mid-1;
            }
            else
                l=mid+1;
        }
        printf("%I64d\n",ans);
    }
}

 

posted @ 2015-09-25 00:06  sweat123  阅读(187)  评论(0编辑  收藏  举报