zoukankan      html  css  js  c++  java
  • bzoj4898 & loj2308 [Apio2017]商旅 最短路+01分数规划

    题目传送门

    https://lydsy.com/JudgeOnline/problem.php?id=4898

    https://loj.ac/problem/2308

    题解

    发现我们可以把整个环路分成很多段,每一段都携带着一个物品。

    那么从 (x)(y) 的这一段,我们可以预处理出应该选择什么物品。可以发现这个是不会变化的。

    于是我们可以视为问题转化为了这样一个问题:给定一个有向完全图,每一条边有一个价值 (w),还有一个费用 (t),选择一个环,使得 (frac{sum w}{sum t}) 最大。

    这显然是一个分数规划的模型,于是直接二分,每条边的边权是一个 (w-midcdot t),只需要判断有没有非负的环就可以了,可以使用 (spfa)


    代码如下,时间复杂度为 (nmlog W)

    #include<bits/stdc++.h>
    
    #define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
    #define dbg(...) fprintf(stderr, __VA_ARGS__)
    #define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
    #define fi first
    #define se second
    #define pb push_back
    
    template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
    template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;}
    
    typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;
    
    template<typename I> inline void read(I &x) {
    	int f = 0, c;
    	while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
    	x = c & 15;
    	while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
    	f ? x = -x : 0;
    }
    
    const int N = 100 + 7;
    const int M = 10000 + 7;
    const int K = 1000 + 7;
    const int INF = 0x3f3f3f3f;
    const ll INF_ll = 0x3f3f3f3f3f3f3f3f;
    
    int n, m, k, maxw, hd, tl;
    int b[N][K], s[N][K]; // b = buy, s = sell
    int f[N][N], w[N][N];
    int num[N], q[N], inq[N];
    ll dis[N], g[N][N];
    
    inline void floyd() {
    	for (int k = 1; k <= n; ++k)
    		for (int i = 1; i <= n; ++i)
    			for (int j = 1; j <= n; ++j)
    				if (i != j) smin(f[i][j], f[i][k] + f[k][j]);
    }
    
    inline void ycl() {
    	for (int i = 1; i <= n; ++i)
    		for (int j = 1; j <= n; ++j)
    			for (int l = 1; l <= k; ++l) if (~s[j][l] && ~b[i][l]) smax(w[i][j], s[j][l] - b[i][l]);
    }
    
    inline void qpush(int x) { ++tl; tl == N ? tl = 1 : 0; q[tl] = x; }
    inline int qhead() { ++hd; hd == N ? hd = 1 : 0; return q[hd]; }
    
    inline bool spfa() {
    	hd = tl = 0;
    	for (int i = 1; i <= n; ++i) dis[i] = -INF_ll, inq[i] = 0, num[i] = 0;
    	dis[1] = 0, qpush(1), inq[1] = 1;
    	while (hd != tl) {
    		int x = qhead();
    		inq[x] = 0;
    		for (int y = 1; y <= n; ++y) if (y != x && dis[y] <= dis[x] + g[x][y]) {
    			dis[y] = dis[x] + g[x][y], num[y] = num[x] + 1;
    			if (num[y] >= n) return 1;
    			if (!inq[y]) qpush(y), inq[y] = 1;
    		}
    	}
    	return 0;
    }
    
    inline bool check(const int &mid) {
    	for (int i = 1; i <= n; ++i)
    		for (int j = 1; j <= n; ++j)
    			g[i][j] = w[i][j] - (ll)mid * f[i][j];
    	return spfa();
    }
    
    inline void work() {
    	floyd();
    	ycl();
    	int l = 0, r = maxw;
    	while (l < r) {
    		int mid = (l + r + 1) >> 1;
    		if (check(mid)) l = mid;
    		else r = mid - 1;
    	}
    	printf("%d
    ", l);
    }
    
    inline void init() {
    	read(n), read(m), read(k);
    	for (int i = 1; i <= n; ++i)
    		for (int j = 1; j <= k; ++j)
    			read(b[i][j]), read(s[i][j]);
    	int x, y, z;
    	for (int i = 1; i <= n; ++i)
    		for (int j = 1; j <= n; ++j)
    			if (i == j) f[i][j] = 0;
    			else f[i][j] = INF;
    	for (int i = 1; i <= m; ++i) read(x), read(y), read(z), smin(f[x][y], z), smax(maxw, z);
    }
    
    int main() {
    #ifdef hzhkk
    	freopen("hkk.in", "r", stdin);
    #endif
    	init();
    	work();
    	fclose(stdin), fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    Median Value
    237. Delete Node in a Linked List
    206. Reverse Linked List
    160. Intersection of Two Linked Lists
    83. Remove Duplicates from Sorted List
    21. Merge Two Sorted Lists
    477. Total Hamming Distance
    421. Maximum XOR of Two Numbers in an Array
    397. Integer Replacement
    318. Maximum Product of Word Lengths
  • 原文地址:https://www.cnblogs.com/hankeke/p/bzoj4898.html
Copyright © 2011-2022 走看看