zoukankan      html  css  js  c++  java
  • LGR-084 C Reboot from Blue 贪心 DAG上DP最短路

    LGR-084 C Reboot from Blue 贪心 DAG上DP最短路

    题意

    数轴上有(n)个加油站,第(i)个位于(x_i),油价为每升(c_i)

    起点坐标(s),终点(t),车油箱一开始是空的,且保证起点处有加油站,假设箱子容量无限大,一升油可以走距离1

    求出最小花费

    [1 leq n leq 10^5\ -10^9 leq x_i,s,t leq 10^9,s < t ]

    分析

    容易想到此题是 51nod1288 的改编

    我们肯定贪心地每次走到下一个价格比当前位置小的位置加油,这一性质就可以用单调栈维护,有考虑到这题由往回走的可能性,所以需要一定转化。

    对于当前点和左右第一个小于当前点的点连边,边权为距离乘油价,容易知道这样可以构成一张DAG,因此最后只需要在DAG上跑最短路即可,这可以用拓扑排序DP实现。

    注意点:1.起点应该保证入度为0,否则无法拓扑排序 2.单调栈实现时,必须找严格小于的位置,否则会形成环。 3.拓扑排序时,一开始必须把所有入度为0的点加入队列,否则可能导致一些点入度始终不能到0的情况

    代码

    #include<bits/stdc++.h>
    #define pii pair<int,ll>
    #define fi first
    #define se second
    #define re register
    using namespace std;
    typedef long long ll;
    
    const ll MOD = 1e9 + 7;
    const int maxn = 1e5 + 5;
    
    ll rd(){
    	ll x = 0;
    	int f = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9') {
    		if(ch == '-') f = -1;
    		ch = getchar();
    	}
    	while(ch >= '0' && ch <= '9') {
    		x = x * 10 + ch - '0';
    		ch = getchar();
    	}
    	return x * f;
    }
    
    struct Edge{
    	int v;
    	ll w;
    	Edge(int _v,ll _w) :v(_v),w(_w) {}
    };
    
    pii p[maxn];
    ll dp[maxn];
    vector<Edge> e[maxn];
    int in[maxn];
    
     
    int main(){
    	int n = rd();
    	int s = rd();
    	int t = rd();
    	for(int i = 1;i <= n;i++){
    		p[i].se = rd();
    		p[i].fi = rd();
    	}
    	p[++n] = make_pair(t,0);
    	sort(p + 1,p + n + 1);
    	int ss,tt;
    	ss = tt = 1;
    	for(int i = 1;i <= n;i++)
    		if(p[i].fi == s) ss = i;
    		else if(p[i].fi == t && !p[i].se) tt = i;
    	
    	stack<int> st;
    	for(int i = 1;i <= n;i++){
    		while(!st.empty() && p[i].se <= p[st.top()].se) {
    			st.pop();
    		}
    		if(!st.empty()) e[i].push_back(Edge(st.top(),p[i].se * (p[i].fi - p[st.top()].fi))),in[st.top()]++;
    		if(i ^ ss)
    			st.push(i); 
    	}
    	
    	while(!st.empty()) st.pop();
    	for(int i = n;i >= 1;i--){
    		while(!st.empty() && p[i].se <= p[st.top()].se) {
    			st.pop();
    		}
    		if(!st.empty()) e[i].push_back(Edge(st.top(),-1 * p[i].se * (p[i].fi - p[st.top()].fi))),in[st.top()]++;
    		if(i ^ ss)
    			st.push(i); 
    	}
    	
    	queue<int> q;
    	for(int i = 1;i <= n;i++)
    		if(!in[i]) q.push(i);
    	for(int i = 1;i <= n;i++)
    		dp[i] = 5e18;
    	dp[ss] = 0;
    	while(!q.empty()) {
    		int u = q.front();
    		q.pop();
    		for(auto v:e[u]) {
    			if(dp[v.v] > dp[u] + v.w)
    				dp[v.v] = dp[u] + v.w;
    			if(!--in[v.v])
    				q.push(v.v);
    		}
    	} 
    	cout << dp[tt];
    }
    
  • 相关阅读:
    caffe常用层: batchNorm层和scale层
    简述configure、pkg-config、pkg_config_path三者的关系
    python删除list中元素的三种方法
    Leetcode 872. Leaf-Similar Trees
    Leetcode 508. Most Frequent Subtree Sum
    Leetcode 572. Subtree of Another Tree
    Leetcode 894. All Possible Full Binary Trees
    Leetcode 814. Binary Tree Pruning
    Leetcode 557. Reverse Words in a String III
    python 多维list声明时的小问题
  • 原文地址:https://www.cnblogs.com/hznumqf/p/14648481.html
Copyright © 2011-2022 走看看