zoukankan      html  css  js  c++  java
  • [APIO2017]商旅(分数规划,spfa)

    题面

    luogu

    题意

    n点m边有向图,k种商品,每种商品在每个点有一个售价和收购价
    (可能存在点不支持某种商品的买卖)
    同一时刻只能携带一种商品,求一个回路使得收益最大
    答案向下取整
    (1 leq N leq 100,1 leq M leq 9900, 1 leq K leq 1000)

    题解

    12opts很简单 处理出每个点到1的最短路,最大收益和从1到达的最短路即可
    开始想的是分数规划+无源汇最大费用最大流check
    两点之间的边就是在这两点做购入售出的最大收益减去mid * dis
    然后发现这个无源汇最大费用最大流要求为正数还要成环感觉没法做怎么又这么熟悉
    于是用spfa判负环就好了。。

    #include <cstdlib>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <queue>
    #include <vector>
    #include <map>
    #define Dis(x, y, z) (w[x][y] - road[x][y] * z)
    using namespace std;
    const int N = 105;
    const int K = 1005;
    const long long inf = 1e18;
    int n, m, k;
    long long road[N][N], w[N][N];
    int b[N][K], s[N][K];
    inline int getmx(int x, int y){
    	int res = 0;
    	for(int i = 1; i <= k; ++i) if(~s[y][i] && ~b[x][i]) res = max(res, s[y][i] - b[x][i]);
    	return res;
    }
    queue<int> que; 
    bool vis[N];
    int cnt[N]; long long dis[N];
    inline bool check(int W){
        //printf("W = %d
    ", W);
    	memset(dis, 0, sizeof(dis));
    	while(!que.empty()) que.pop();
    	for(int i = 1; i <= n; ++i) que.push(i), vis[i] = 1, cnt[i] = 0;
    	while(!que.empty()){
    		int fro = que.front(); que.pop(); vis[fro] = 0;
    		if(++cnt[fro] > n) return 1;
    		for(int i = 1; i <= n; ++i) if(fro != i){
    			//if(road[fro][i] < inf && W < 5) printf("%d %d %lld %lld
    ", fro, i, dis[i], road[fro][i] * W - w[fro][i]);
    			if(road[fro][i] < inf && dis[i] >= dis[fro] + (road[fro][i] * W - w[fro][i])){
    				dis[i] = dis[fro] + (road[fro][i] * W - w[fro][i]);
    				if(!vis[i]) que.push(i), vis[i] = 1;
    			}
    		}
    	}
    	//printf("Yeah!
    ");
    	return 0;
    } 
    int main(){
    	scanf("%d%d%d", &n, &m, &k);
    	for(int i = 1; i <= n; ++i)
    		for(int j = 1; j <= k; ++j)
    		    scanf("%d%d", &b[i][j], &s[i][j]);
    	for(int i = 1; i <= n; ++i){
    	    for(int j = 1; j <= n; ++j) road[i][j] = inf;
    		road[i][i] = 0;
    	}
    	for(int i = 1, x, y, z; i <= m; ++i)
    		scanf("%d%d%d", &x, &y, &z), road[x][y] = z;
    	for(int p = 1; p <= n; ++p)
    	    for(int i = 1; i <= n; ++i) if(i != p)
    	        for(int j = 1; j <= n; ++j) if(j != i && j != p){
    	            road[i][j] = min(road[i][j], road[i][p] + road[p][j]);	
    	        }
    	for(int i = 1; i <= n; ++i)
    	    for(int j = 1; j <= n; ++j)
    	        w[i][j] = getmx(i, j);
    	int l = 0, r = 1e9, mid, ret;
    	while(l < r){
    		mid = l + ((r - l + 1) >> 1);
    		if(check(mid)) l = mid;
    		else r = mid - 1;
    	}
    	printf("%d
    ", l);
    	return 0;
    }
    
  • 相关阅读:
    OutputCache 缓存key的创建 CreateOutputCachedItemKey
    Asp.net Web Api源码调试
    asp.net mvc源码分析DefaultModelBinder 自定义的普通数据类型的绑定和验证
    Asp.net web Api源码分析HttpParameterBinding
    Asp.net web Api源码分析HttpRequestMessage的创建
    asp.net mvc源码分析ActionResult篇 RazorView.RenderView
    Asp.Net MVC 项目预编译 View
    Asp.net Web.config文件读取路径你真的清楚吗?
    asp.net 动态创建TextBox控件 如何加载状态信息
    asp.net mvc源码分析BeginForm方法 和ClientValidationEnabled 属性
  • 原文地址:https://www.cnblogs.com/hjmmm/p/10808785.html
Copyright © 2011-2022 走看看