题目描述
Farmer John 最近为了扩张他的牛奶产业帝国而收购了一个新的农场。这一新的农场通过一个管道网络与附近的小镇相连,FJ 想要找出其中最合适的一组管道,将其购买并用来将牛奶从农场输送到小镇。
这个管道网络可以用 N 个接合点(管道的端点)来描述,将其编号为 1…N。接合点 1 表示 FJ 的农场,接合点 N 表示小镇。有 M 条双向的管道,每条连接了两个接合点。使用第 i 条管道需要 FJ 花费 ci 美元购入,可以支持每秒 fi 升牛奶的流量。
FJ 想要购买一条管道组成一条单一路径,路径的两端点分别为接合点 1 和 N。这条路径的花费等于路径上所有管道的费用之和。路径上的流量等于路径上所有管道的最小流量(因为这是沿这条路径输送牛奶的瓶颈)。FJ 想要最大化路径流量与路径花费之比。保证存在从 1 到 N之间的路径。
输入格式
输入的第一行包含 N 和 M。以下 M 行每行以四个整数描述一条管道:a 和 b(管道连接的两个不同的接合点),c(管道的花费),以及 f(管道的流量)。花费和流量均为范围 1…1000 之内的正整数。
输出格式
输出 10^6 乘以最优解的值,并向下取整(也就是说,如果这个数本身不是整数,输出小于它的最接近它的整数)。
输入输出样例
输入 #1复制
3 2 2 1 2 4 2 3 5 3输出 #1复制
428571说明/提示
在这个例子中,仅由一条路径从 1 到 N。 它的流量为min(3,4)=3,花费为 2+5=7。
数据范围
测试点 2∼5 满足 N,M≤100。
对于 100% 的数据,2≤N≤1000,1≤M≤1000。
供题:Brian Dean
代码:
#include <bits/stdc++.h>
using namespace std;
#define PII pair<int,int>//宏定义
#define int long long
int n,m,l,r;
int dis[1000010];
bool vis[1000010];
vector<pair<int,pair<int,int>>> e[1000010];
bool check(int mid){//dijkstra模板 改动
for(int i = 1;i<=n;i++){
dis[i]=1e18;
vis[i]=0;
}
priority_queue<PII,vector<PII>,greater<PII> > q;
q.push({0,1});
dis[1]=0;
while(q.size()){
auto t=q.top();
q.pop();
auto now=t.second;
if(vis[now]) continue;
vis[now]=1;
for(auto tt:e[now]){
auto a=tt.first;
auto b=tt.second;
if(b.second>=mid&&dis[a]>dis[now]+b.first){
//判断经过的所有管子流量是否都大于mid,路径花费是否更小
dis[a]=dis[now]+b.first;
q.push({dis[a],a});//入队
}
}
}
if(dis[n]==1e18) return 0;//如果dis[n]==1e18,说明这个流量情况下不能到达n点
else return 1;
}
signed main(){
cin >> n >> m;
for(int i = 1;i<=m;i++){
int a,b,c,f;
cin >> a >> b >> c >> f;
l=min(l,f);
r=max(r,f);
e[a].push_back({b,{c,f}});
e[b].push_back({a,{c,f}});
}
int maxn=-1e18;//初始化为极小值
for(int i = l;i<=r;i++){//从管道的最小流量到最大流量遍历求,而不是从1-1000,更少计算
if(check(i)){
int now=(double)i/dis[n]*1e6;
maxn=max(maxn,now);//得较大值
}
}
cout << maxn;
return 0;
}