zoukankan      html  css  js  c++  java
  • [LOJ2759] JOI2014 Final 飞天鼠

    问题描述

    有n棵树,每棵树高度h[i],老鼠一开始在树1,高度为x。

    有m条边,每条边(u,v,t),从树u到树v需要t的时间,并且到达树v之后高度会下降t。

    在每棵树上时,可以花费1的时间使高度+1或-1。如果在树i,高度不能超过这棵树的高度。

    现在老鼠想到n的顶端,求最短时间。

    N<=1e5

    解析

    我们先贪心的想一想,最后的某条合法最短路径一定是长这样:先一直下降高度,直到高度为零,然后每次都上升到需要的高度后再飞。这样就不会出现明明能够飞、但是高度不够而导致花费不必要的代价的情况。这样我们在跑最短路的同时记录一下当前所在点的高度,然后讨论一下就可以了。

    不要用自己定义的结构体跑优先队列,会很慢。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <cmath>
    #define int long long
    #define N 100002
    #define M 300002
    using namespace std;
    int head[N],ver[M*2],nxt[M*2],edge[M*2],l;
    int n,m,x,i,h[N],h2[N],dis[N];
    priority_queue<pair<int,int> > q;
    int read()
    {
    	char c=getchar();
    	int w=0;
    	while(c<'0'||c>'9') c=getchar();
    	while(c<='9'&&c>='0'){
    		w=w*10+c-'0';
    		c=getchar();
    	}
    	return w;
    }
    void insert(int x,int y,int z)
    {
    	l++;
    	ver[l]=y;
    	edge[l]=z;
    	nxt[l]=head[x];
    	head[x]=l;
    }
    void Dijkstra(int now)
    {
    	memset(dis,0x3f,sizeof(dis));
    	q.push(make_pair(0,1));dis[1]=0;h2[1]=now;
    	while(!q.empty()){
    		int x=q.top().second,d=-q.top().first,h1=h2[x];
    		q.pop();
    		if(dis[x]!=d) continue;
    		for(int i=head[x];i;i=nxt[i]){
    			int y=ver[i],w=dis[0],tmp;
    			if(h1==0&&edge[i]<=h[x]) w=2*edge[i],tmp=0;
    			else if(h1-edge[i]>h[y]) w=h1-h[y],tmp=h[y];
    			else if(h1-edge[i]<0&&edge[i]<=h[x]) w=2*edge[i]-h1,tmp=0;
    			else if(h1-edge[i]>=0&&h1-edge[i]<=h[y]) w=edge[i],tmp=h1-edge[i];
    			if(w!=dis[0]&&dis[y]>dis[x]+w){
    				dis[y]=dis[x]+w;h2[y]=tmp;
    				q.push(make_pair(-dis[y],y));
    			}
    		}
    	}
    	dis[n]+=abs(h[n]-h2[n]);
    }
    signed main()
    {
    	n=read();m=read();x=read();
    	for(i=1;i<=n;i++) h[i]=read();
    	for(i=1;i<=m;i++){
    		int u=read(),v=read(),w=read();
    		insert(u,v,w);insert(v,u,w);
    	}
    	Dijkstra(x);
    	if(dis[n]>=dis[0]) puts("-1");
    	else printf("%lld
    ",dis[n]);
    	return 0;
    }
    
  • 相关阅读:
    第一篇Scrum冲刺博客
    团队作业3--需求改进&系统设计
    团队作业2(追忆少年)—需求规格说明书
    JAVA作业—字符串操作
    团队作业1——团队展示&选题 (追忆少年)
    个人项目作业WC(JAVA)
    自我介绍+软工5问
    C语言I博客作业07
    C语言I博客作业06
    C语言I博客作业05
  • 原文地址:https://www.cnblogs.com/LSlzf/p/13971682.html
Copyright © 2011-2022 走看看