「JOI 2014 Final」飞天鼠

「JOI 2014 Final」飞天鼠

显然向上爬是没有必要的,除非会下降到地面以下,才提高到刚好为0。

到达一个点有两种情况:到达高度为0和不为0。

对于高度不为0的情况,显然花费的时间越少高度越高(每下降1m都要1单位时间),而必然高度越高越好,因此只需求花费的最少时间。

对于高度为0的情况,显然花费的时间越少越好。

高度不为0的情况比高度为0的情况要优越,而且事实上,高度不为0的情况花费必然会小于高度为0的情况。因此两种情况可以直接合并。

故可以直接dijkstra跑一遍。

复杂度(o(mlog(m)))

#include<bits/stdc++.h>
#define rep(q,a,b) for(int q=a,q##_end_=b;q<=q##_end_;++q)
#define dep(q,a,b) for(int q=a,q##_end_=b;q>=q##_end_;--q)
#define mem(a,b) memset(a,b,sizeof a )
using namespace std;
typedef long long ll;
char buf[15000000],*p1=buf,*p2=buf;
#define Getchar() p1==p2?EOF:*p1++
void in(int &r) {
	static char c;
	r=0;
	while(c=Getchar(),c<48);
	do r=(r<<1)+(r<<3)+(c^48);
	while(c=Getchar(),c>47);
}
const int mn=100005;
const int mm=300005;
int head[mn],ne[mm<<1],to[mm<<1],cost[mm<<1],cnt1;
#define link_edge(a,b,c) to[++cnt1]=b,ne[cnt1]=head[a],head[a]=cnt1,cost[cnt1]=c
#define travel(x) for(int q(head[x]);q;q=ne[q])
int val[mn];
int n,m;
ll sum[mn];
int H[mn];
bool mark[mn];
struct node {
	ll v;
	int id;
	bool operator <(const node &A)const {
		return v>A.v;
	}
};
priority_queue<node> qw;
void WA(int at) {
	
	rep(q,1,n)sum[q]=1e18;
	qw.push({0,1}),H[1]=at,sum[1]=0;
	ll v;
	while(!qw.empty()) {
		node now=qw.top();
		qw.pop();
		if(mark[now.id])continue;
		mark[now.id]=1;
		int h=H[now.id];
		travel(now.id) {
			if(h-cost[q]>val[to[q]]) {
				v=sum[now.id]+h-cost[q]-val[to[q]]+cost[q];
				if(sum[to[q]]>v) {
					sum[to[q]]=v;
					H[to[q]]=val[to[q]];
					qw.push({sum[to[q]],to[q]});
				}
			} else if(h-cost[q]<0) {
				v=sum[now.id]+cost[q]-h+cost[q];
				if(sum[to[q]]>v) {
					sum[to[q]]=v;
					H[to[q]]=0;
					qw.push({sum[to[q]],to[q]});
				}
			} else {
				if(sum[to[q]]>sum[now.id]+cost[q]) {
					sum[to[q]]=sum[now.id]+cost[q];
					H[to[q]]=h-cost[q];
					qw.push({sum[to[q]],to[q]});
				}
			}
		}
	}
}
int main() {
    p2=buf+fread(buf,1,15000000,stdin);
	int at;
	in(n),in(m),in(at);
	rep(q,1,n)in(val[q]);
	int a,b,c;
	rep(q,1,m) {
		in(a),in(b),in(c);
		if(val[a]>=c)link_edge(a,b,c);
		if(val[b]>=c)link_edge(b,a,c);
	}
	WA(at);
	if(sum[n]==1e18)puts("-1");
	else printf("%lld
",sum[n]+val[n]-H[n]);
	return 0;
}
原文地址:https://www.cnblogs.com/klauralee/p/11305457.html