洛谷 P5837 [USACO19DEC]Milk Pumping G(dijkstra,分数规划)

传送门


解题思路

分数规划问题:最大化比值。
可以枚举流量,再dijkstra跑最短路求出费用,更新答案。

AC代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
using namespace std;
const int maxn=1005;
int n,m,dis[maxn],p[maxn],cnt;
long long ans;
struct node{
	int v,next,w,f;
}e[maxn*2];
void insert(int u,int v,int w,int f){
	cnt++;
	e[cnt].v=v;
	e[cnt].f=f;
	e[cnt].w=w;
	e[cnt].next=p[u];
	p[u]=cnt;
}
int dij(int x){
	memset(dis,0x3f,sizeof(dis));
	set<pair<int,int> > s;
	dis[1]=0;
	s.insert(make_pair(0,1));
	while(!s.empty()){
		int u=s.begin()->second;
		s.erase(s.begin());
		if(u==n) return dis[n];
		for(int i=p[u];i!=-1;i=e[i].next){
			if(e[i].f<x) continue;
			int v=e[i].v;
			if(dis[v]>dis[u]+e[i].w){
				s.erase(make_pair(dis[v],v));
				dis[v]=dis[u]+e[i].w;
				s.insert(make_pair(dis[v],v));
			}
		}
	}
	return dis[n];
}
int main(){
	ios::sync_with_stdio(false);
	memset(p,-1,sizeof(p));
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		int u,v,c,f;
		cin>>u>>v>>c>>f;
		insert(u,v,c,f);
		insert(v,u,c,f);
	}
	for(int i=1;i<=1000;i++){
		ans=max(ans,(long long)(1000000*i/dij(i)));
	}
	cout<<ans;
	return 0;
}
原文地址:https://www.cnblogs.com/yinyuqin/p/15344702.html