题目描述
有n个点、m条边、和k种商品。第$i$个点可以以$B_{ij}$的价格买入商品$j$,并以$S_{ij}$的价格卖出。任何时候只能持有一个商品。求一个环,使得初始不携带商品时以某种交易方式走过一圈所得的利润/路径长度(向下取整)最大。
输入
输出
样例输入
4 5 2
10 9 5 2
6 4 20 15
9 7 10 9
-1 -1 16 11
1 2 3
2 3 3
1 4 1
4 3 1
3 1 1
样例输出
2
题解
Floyd+分数规划+Spfa
题目显然是一个分数规划的模型,但是如果直接使用分层图模拟商品买卖的过程的话肯定会TLE。
我们不妨换个思路:考虑每件两点之间的连续交易。即在A地购买商品,并在B地卖出的这个过程。
那么这个过程走的一定是最短路,买卖的一定是盈利最大的商品(当无法盈利时显然不进行买卖,盈利为0)。
所以可以使用Floyd求出任意两点之间最短路,再处理出来任意两点之间的最大盈利。
然后就可以对这个图求最大比率环了。二分答案,把每条边的权值看作 最大盈利-最短路*mid ,如果有非负环则说明mid成立,否则mid不成立。
时间复杂度$O(n^2k+n^3\log v)$。
#include <queue>
#include <cstdio>
#include <cstring>
#define N 110
#define K 1010
using namespace std;
typedef long long ll;
queue<int> q;
int n , len[N][N] , val[N][N] , b[N][K] , s[N][K] , inq[N] , num[N];
ll dis[N];
inline bool judge(int mid)
{
	int x , i;
	while(!q.empty()) q.pop();
	for(i = 1 ; i <= n ; i ++ ) dis[i] = inq[i] = num[i] = 0 , q.push(i);
	while(!q.empty())
	{
		x = q.front() , q.pop() , inq[x] = 0;;
		for(i = 1 ; i <= n ; i ++ )
		{
			if(dis[i] <= dis[x] + val[x][i] - (ll)mid * len[x][i])
			{
				dis[i] = dis[x] + val[x][i] - (ll)mid * len[x][i];
				if(!inq[i])
				{
					if(num[i] == n) return 1;
					num[i] ++ , inq[i] = 1 , q.push(i);
				}
			}
		}
	}
	return 0;
}
int main()
{
	int m , p , i , j , k , x , y , z , l = 1 , r = 0 , mid , ans = 0;
	scanf("%d%d%d" , &n , &m , &p);
	for(i = 1 ; i <= n ; i ++ )
		for(j = 1 ; j <= p ; j ++ )
			scanf("%d%d" , &b[i][j] , &s[i][j]);
	for(i = 1 ; i <= n ; i ++ )
		for(j = 1 ; j <= n ; j ++ )
			for(k = 1 ; k <= p ; k ++ )
				if(~b[i][k] && ~s[j][k])
					val[i][j] = max(val[i][j] , s[j][k] - b[i][k]);
	memset(len , 0x3f , sizeof(len));
	for(i = 1 ; i <= m ; i ++ ) scanf("%d%d%d" , &x , &y , &z) , len[x][y] = z , r = max(r , z);
	for(k = 1 ; k <= n ; k ++ )
		for(i = 1 ; i <= n ; i ++ )
			for(j = 1 ; j <= n ; j ++ )
				len[i][j] = min(len[i][j] , len[i][k] + len[k][j]);
	while(l <= r)
	{
		mid = (l + r) >> 1;
		if(judge(mid)) ans = mid , l = mid + 1;
		else r = mid - 1;
	}
	printf("%d\n" , ans);
	return 0;
}
【bzoj4898】[Apio2017]商旅 Floyd+分数规划+Spfa
原文:http://www.cnblogs.com/GXZlegend/p/7570573.html