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;
}
posted @ 2022-01-26 15:10  蒟蒻xiezheyuan  阅读(34)  评论(0编辑  收藏  举报