poj 3228 Gold Transportation(二…

来源:互联网 发布:ar9565 linux 编辑:程序博客网 时间:2024/05/18 09:39
题意:有N座town 每座town都有一定数量gold和仓库 仓库的容量是有限的 有M条双向路径 求把所有的gold运到仓库最小的最大距离是多少。

思路:跟前几天做的那道poj 2112 Optimal Milking 的思想是一样的,建图时,超级源点与gold相连容量为gold的数量,超级汇点与仓库相连,容量为仓库的容量,其余边为无穷。用二分枚举求出最小的最距离 求最大流的时候,我用的是EK算法 主要是代码短,虽然时间效率是有点低。

//656K   797MS
#include <stdio.h>
#include <string.h>
#define VM 250
#define EM 20010
#define inf 0x3f3f3f3f
int pre[VM],mat[VM][VM],dist[VM][VM];
int gold[VM],stor[VM];
int n,m,total,src,des;

void Build (int num)  //在当前距离下 给通过的路径
{
    memset(mat,0,sizeof(mat));
    inti,j;
    for (i = 1;i<= n;i ++)
       for (j = 1;j <= n;j ++)
           if (dist[i][j] <= num)
               mat[i][j] = inf;
    for (i = 1;i<= n;i ++)
    {
       mat[src][i] = gold[i];
       mat[i][des] = stor[i];
    }
}

bool BFS ()
{
    intque[VM+5];
    memset(pre,0xff,sizeof(pre));
    int front =0,rear = 0;
    pre[src] =0;
    que[rear++]= src;
    while (front!= rear)
    {
       int u = que[front ++];
       front = front%VM;
       for (int v = 1;v <= des;v ++)
       {
           if (pre[v] != -1||mat[u][v] == 0)
               continue;
           pre[v] = u;
           if (v == des)
               return true;
           que[rear++] = v;
           rear = rear%VM;
       }
    }
    returnfalse;
}
intEK()       //EK()算法,
{
    int res =0,i;
    while(BFS())
    {
       int min = inf;
       for (i = des;i != src;i = pre[i])
           min = min > mat[pre[i]][i] ?mat[pre[i]][i]:min;
       res += min;
       for (i = des;i != src;i = pre[i])
       {
           mat[pre[i]][i] -= min;
           mat[i][pre[i]] += min;
       }
    }
    returnres;
}
int main ()
{
   //freopen("in.txt","r",stdin);
    inti,u,v,w;
    while(~scanf("%d",&n)&&n)
    {
       memset (dist,0x3f,sizeof(dist));
       total =0;           //total是总的gold数
       src = 0,des = n+1;
       for (i = 1; i <= n; i ++)
       {
           scanf ("%d",&gold[i]);
           total += gold[i];
       }
       for (i = 1; i <= n; i ++)
           scanf ("%d",&stor[i]);
       scanf ("%d",&m);
       while (m --)
       {
           scanf("%d%d%d",&u,&v,&w);
           dist[u][v] = w;
           dist[v][u] = w;
       }
       int l = 0,r = 10001;
       int ans = -1;
       while (l <= r)
       {
           int mid = (l + r)>>1;
           Build(mid);
           int sum = EK();
           if (sum >= total)
           {
               ans = mid;
               r = mid -1;
           }
           else
               l = mid + 1;
       }
       if (ans == -1)
           printf ("No Solution\n");
       else
           printf ("%d\n",ans);
    }
    return0;
}

原创粉丝点击