USACO Milk Routing

洛谷 P3063 [USACO12DEC]牛奶的路由Milk Routing

洛谷传送门

JDOJ 2334: USACO 2012 Dec Silver 3.Milk Routing

JDOJ传送门

Description

Problem 3: Milk Routing [Brian Dean, 2012]

Farmer John's farm has an outdated network of M pipes (1 <= M <= 500) for
pumping milk from the barn to his milk storage tank. He wants to remove
and update most of these over the next year, but he wants to leave exactly
one path worth of pipes intact, so that he can still pump milk from the
barn to the storage tank.

The pipe network is described by N junction points (1 <= N <= 500), each of
which can serve as the endpoint of a set of pipes. Junction point 1 is the
barn, and junction point N is the storage tank. Each of the M
bi-directional pipes runs between a pair of junction points, and has an
associated latency (the amount of time it takes milk to reach one end of
the pipe from the other) and capacity (the amount of milk per unit time
that can be pumped through the pipe in steady state). Multiple pipes
can connect between the same pair of junction points.

For a path of pipes connecting from the barn to the tank, the latency
of the path is the sum of the latencies of the pipes along the path,
and the capacity of the path is the minimum of the capacities of the
pipes along the path (since this is the "bottleneck" constraining the
overall rate at which milk can be pumped through the path). If FJ
wants to send a total of X units of milk through a path of pipes with
latency L and capacity C, the time this takes is therefore L + X/C.

Given the structure of FJ's pipe network, please help him select a single
path from the barn to the storage tank that will allow him to pump X units
of milk in a minimum amount of total time.

Input

* Line 1: Three space-separated integers: N M X (1 <= X <= 1,000,000).

* Lines 2..1+M: Each line describes a pipe using 4 integers: I J L C.
I and J (1 <= I,J <= N) are the junction points at both ends
of the pipe. L and C (1 <= L,C <= 1,000,000) give the latency
and capacity of the pipe.

Output

* Line 1: The minimum amount of time it will take FJ to send milk
along a single path, rounded down to the nearest integer.

Sample Input

3 3 15 1 2 10 3 3 2 10 2 1 3 14 1

Sample Output

27

HINT

INPUT DETAILS:

FJ wants to send 15 units of milk through his pipe network. Pipe #1
connects junction point 1 (the barn) to junction point 2, and has a latency
of 10 and a capacity of 3. Pipes #2 and #3 are similarly defined.

OUTPUT DETAILS:

The path 1->3 takes 14 + 15/1 = 29 units of time. The path 1->2->3 takes
20 + 15/2 = 27.5 units of time, and is therefore optimal.

题目翻译:

农民约翰的农场有一套老旧的管网,管网由M条管道(1<=M<=500)构成,用于将牛奶从谷仓运到储奶罐。 他想在明年移除和更新大部分管道,但他想原封不动地保留一条完整的路径,这样他仍然可以把牛奶从谷仓输送到储罐。

管网由N个节点(1<=N<=500)组成,每个点都可以作为一组管道的端点。结点1是谷仓,结点N是储罐。M条双向管道中的每一条都连接一对节点,并且都有一个延迟值(牛奶达到管的另一端的用时)和容量值(单位时间内可以稳定通过管道的牛奶量)。多条管道可以连接同一对节点。

对于一条连接谷仓与储罐的路径,路径的延迟等于沿途所有管道的延迟之和,路径的容量等于沿途管道最小的容量(因为这是制约牛奶运送的“瓶颈”)。如果约翰通过一条延迟为L、容量为C的管道运送X个单位的牛奶,需要的时间为L+X/C。

给出约翰的管网结构,请帮助他选择一条路径,使得他从谷仓到储罐运送X个单位牛奶的总时间最少。

题解:

一道图论中的最短路变形题目。

我的题意又理解错了,不要以为是单纯的松弛时间就可以了。这道题的坑点在于,你的一条路径的时间计算中的C其实是整条路径的C的最小值。

所以我们就不能直接拍板子了。

那我们怎么解决跑最短路的时候还能维护时间呢?

直观一点想,我们在每次松弛的时候可以维护一个可行的最短时间。

所以我们就想到了,能不能在SPFA的模板中加一个参数,使得它能够不断地被更新,达到松弛时间的目的呢?

我们可以实现,具体方式是新开一个数组,然后保存每条边的需要时间,最后枚举和跑SPFA的时候直接按这个时间枚举即可。

代码:

#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
#pragma GCC optimize(2)
using namespace std;
int n,m,t,ans=1e9;
int tot,to[1001],vall[1001],valc[1001],nxt[1001],head[501],c[501];
int f[501];
bool v[501];
inline int read(){
   int s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}
void add(int x,int y,int zl,int zc)
{
    to[++tot]=y;
    vall[tot]=zl;
    valc[tot]=zc;
    nxt[tot]=head[x];
    head[x]=tot;
}
void spfa(int w)
{
    memset(f,0x3f,sizeof(f));
    memset(v,0,sizeof(v));
    queue<int> q;
    q.push(1);
    v[1]=1;
    f[1]=0;
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        v[x]=0;
        for(int i=head[x];i;i=nxt[i])
        {
            int y=to[i];
            if(f[y]>f[x]+vall[i] && valc[i]>=w)
            {
                f[y]=f[x]+vall[i];
                if(v[y]==0)
                {
                    q.push(y);
                    v[y]=1;
                }
            }
        }
    }
}
int main()
{
    n=read();
    m=read();
    t=read();
    for(int i=1;i<=m;i++)
    {
        int x,y,zl,zc;
        x=read();
        y=read();
        zl=read();
        zc=read();
        add(x,y,zl,zc);
        add(y,x,zl,zc);
        c[i]=zc;
    }
    for(int i=1;i<=m;i++)
    {
        spfa(c[i]);
        ans=min(ans,f[n]+t/c[i]);
    }
    printf("%d",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/fusiwei/p/11330890.html