P3063 [USACO12DEC]Milk Routing S
题面
农民约翰的农场有一套老旧的管网,管网由 \(M\) 条管道( $1 \le M \le 500 $ )构成,用于将牛奶从谷仓运到储奶罐。 他想在明年移除和更新大部分管道,但他想原封不动地保留一条完整的路径,这样他仍然可以把牛奶从谷仓输送到储罐。
管网由 \(N\) 个节点( \(1 \le N \le 50\) )组成,每个点都可以作为一组管道的端点。结点 \(1\) 是谷仓,结点 \(N\) 是储罐。 \(M\) 条双向管道中的每一条都连接一对节点,并且都有一个延迟值(牛奶达到管的另一端的用时)和容量值(单位时间内可以稳定通过管道的牛奶量)。多条管道可以连接同一对节点。
对于一条连接谷仓与储罐的路径,路径的延迟等于沿途所有管道的延迟之和,路径的容量等于沿途管道最小的容量(因为这是制约牛奶运送的“瓶颈”)。如果约翰通过一条延迟为 \(L\) 、容量为 \(C\) 的管道运送 \(X\) 个单位的牛奶,需要的时间为 \(\frac{L+X}{C}\) 。
给出约翰的管网结构,请帮助他选择一条路径,使得他从谷仓到储罐运送X个单位牛奶的总时间最少。
思路
暴力碾标算!
首先,不要乱想,静静地养这不是什么最小费用最大流问题,只是一个简单的最短路问题。
只要枚举流量,跑一个 \(SPFA\) ,求出延迟\(L\),在跑最短路的时候,遇到的一个点,如果比枚举的点小,就不走这个点,枚举完后,得到的就是最大值\(max\)了。
贴上代码
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3ffffff;
struct node{
int w,v;
};
node make_node(int c,int d){
return (node){c , d};
}
int n,m,need,ans=inf;
int h[515],dis[515];
int vis[515];
vector<pair<int,node> > e[515];
void SPFA(int minn){
priority_queue<pair<int,int> > q;
dis[1] = 0;
q.push(make_pair(0,1));
while(!q.empty()){
int x = q.top().second;
q.pop();
if(vis[x]) continue;
vis[x] = 1;
for(int i = 0; i < e[x].size(); i++){
int nx = e[x][i].first , nw = e[x][i].second.w , nv = e[x][i].second.v;
if(nv < minn) {
continue;
}
if(dis[nx] > dis[x] + nw){
dis[nx] = dis[x] + nw;
q.push(make_pair(-dis[nx] , nx));
}
}
}
}
int main(){
scanf("%d%d%d",&n,&m,&need);
for(int i=1;i<=m;i++){
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
h[i]=d;
e[a].push_back(make_pair(b,make_node(c,d)));
e[b].push_back(make_pair(a,make_node(c,d)));
}
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
vis[j]=0;
dis[j]=inf;
}
SPFA(h[i]);
ans=min(ans,dis[n]+need/h[i]);
}
printf("%d",ans);
putchar('\n');
return 0;
}