• 第13回日本情報オリンピック 本選 D


    题目链接:D - フクロモモンガ (Sugar Glider)

    题目大意:有 (n) 棵树和一只猴子,每一棵树有一个高度 (h_i) ,有 (m) 棵树之间可以互相飞行,花费时间是 (t_i) ,并且在飞行过程中,每过一个单位时间高度会下降 (1) ,你在到达一棵树时的高度不能大于这棵树的高度也不能小于零,猴子在一棵树上可以花费一个单位的时间使自己的高度增加 (1) 或减少 (1) ,猴子一开始在第一棵树高度为 (X) 处,问若要爬到第 (n) 棵树的最高处最少要花费多长时间。

    (nleq 10^5,mleq 3cdot 10^5,h_i,t_i,Xleq 10^9)

    Subtask 1: (n,m leq 100,h_ileq 1000) (25 points)

    Subtask 2: (X=0) (25 points)


    题解:考虑 (X=0) 时的弱化版,显然我们可以令到达每一棵树的时候高度都是零,容易证明这样是不劣的,然后考虑 (X) 不为 (0) 的情况,因为前面的若干步每一步都会导致高度下降 (1) ,所以我们求出每一个点的最短路动态计算边权即可。

    使用 Dijkstra 算法跑最短路,时间复杂度 (O(nlog m))

    代码:

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const int Maxn=100000;
    const int Maxm=300000;
    const ll Inf=0x3f3f3f3f3f3f3f3fll;
    int n,m,x;
    int head[Maxn+5],arrive[Maxm<<1|5],nxt[Maxm<<1|5],val[Maxm<<1|5],tot;
    int h[Maxn+5];
    void add_edge(int from,int to,int w){
    	arrive[++tot]=to;
    	nxt[tot]=head[from];
    	val[tot]=w;
    	head[from]=tot;
    }
    ll dis[Maxn+5];
    priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > > q;
    void dij(int s){
    	memset(dis,0x3f,sizeof dis);
    	dis[s]=0;
    	q.push(make_pair(0ll,s));
    	while(!q.empty()){
    		pair<ll,int> u=q.top();
    		q.pop();
    		if(u.first!=dis[u.second]){
    			continue;
    		}
    		for(int i=head[u.second];i;i=nxt[i]){
    			int v=arrive[i];
    			if(h[u.second]-val[i]<0){
    				continue;
    			}
    			ll tmp_dis;
    			if(max(0ll,x-dis[u.second])-val[i]>h[v]){
    				tmp_dis=x-dis[u.second]-h[v];
    			}
    			else{
    				tmp_dis=val[i]+max(0ll,val[i]-max(0ll,x-dis[u.second]));
    			}
    			tmp_dis+=dis[u.second];
    			if(tmp_dis<dis[v]){
    				dis[v]=tmp_dis;
    				q.push(make_pair(tmp_dis,v));
    			}
    		}
    	}
    }
    int main(){
    	scanf("%d%d%d",&n,&m,&x);
    	for(int i=1;i<=n;i++){
    		scanf("%d",&h[i]);
    	}
    	for(int i=1;i<=m;i++){
    		int u,v,w;
    		scanf("%d%d%d",&u,&v,&w);
    		add_edge(u,v,w);
    		add_edge(v,u,w);
    	}
    	dij(1);
    	if(dis[n]>=Inf){
    		puts("-1");
    	}
    	else{
    		printf("%lld
    ",dis[n]+h[n]-max(0ll,x-dis[n]));
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    查找字符串中特定字符最后出现的位置
    C# List中的ForEach
    tensorflow中一个矩阵和一个向量相加
    Hibernate-ORM:16.Hibernate中的二级缓存Ehcache的配置
    Hibernate-ORM:15.Hibernate中的Criteria查询
    Hibernate-ORM:14.Hibernate中的命名查询
    Hibernate-ORM:12.Hibernate中的多对多关联关系
    Hibernate-ORM:10.Hibernate中的分页
    Hibernate-ORM:09.Hibernate中的getCurrentSession()
    Hibernate-ORM:08.Hibernate中的投影查询
  • 原文地址:https://www.cnblogs.com/withhope/p/13854403.html
Copyright © 2020-2023  润新知