dyllalala

导航

[vijos P1880]ファーラの力

 

据说这是一道 JOI 的题?反正我觉着挺好的喵~

 

题目看起来十分可怕,但是代码还是很短的

显而易见的,ans 因分为3个部分:1.中途增加光压的时间 2.中途减少光压的时间 3. 所有路程的总时间

发现如果把每个柱子的光压下限0去掉后,光压无论在何时加都是一样的

因为若从某刻光压小于等于0后,我们可以按需调整光压,就不再出现人为降低光压这个操作,而不论如何最后的光压一定是 E[终点]

所以

1.光压无论在何时加都是一样的

而我们又发现在路径上减少1个光压和在光柱上人为调整1个光压的时间是一样的

光压差就是时间差

我们用dist[n]表示到点n时的光压

2.X-dist[终点]=中途减少光压的时间+所有路程的总时间

又由1得E[终点]-dist[终点]=中途增加光压的时间

这两个式子都是随着dist[终点]的递增而递减的

只要算出最大的dist[终点]即可,这就是为什么要用最短路稍的原因

ans=(X-dist[终点])+(E[终点]-dist[终点)=X+E[终点]-2*dist[终点]

 

 1 #include <cstdio>
 2 #include <queue>
 3 #include <algorithm>
 4 typedef std::pair<long long, int> node;
 5 const long long INF=0x7FFFFFFFFFFFFFLL;
 6 const int sizeOfPoint=100001;
 7 const int sizeOfEdge=600006;
 8 
 9 struct edge {int point, dist; edge * next;};
10 edge memory[sizeOfEdge], * port=memory;
11 edge * e[sizeOfPoint];
12 inline edge * newedge(int point, int dist, edge * next)
13 {
14     edge * ret=port++;
15     ret->point=point; ret->dist=dist; ret->next=next;
16     return ret;
17 }
18 
19 int N, M, X;
20 int E[sizeOfPoint];
21 long long dist[sizeOfPoint];
22 std::priority_queue<node> q;
23 inline long long min(long long x, long long y) {return x<y?x:y;}
24 inline int getint();
25 inline void putint(long long);
26 
27 int main()
28 {
29     N=getint(), M=getint(), X=getint();
30     for (int i=1;i<=N;i++) E[i]=getint();
31     for (int i=0;i<M;i++)
32     {
33         int A, B, T;
34         A=getint(), B=getint(), T=getint();
35         if (E[A]>=T) e[A]=newedge(B, T, e[A]);
36         if (E[B]>=T) e[B]=newedge(A, T, e[B]);
37     }
38 
39     for (int i=1;i<=N;i++) dist[i]=-INF;
40     for (q.push(node(X, 1));!q.empty(); )
41     {
42         node u=q.top(); q.pop();
43         if (dist[u.second]!=-INF) continue;
44         dist[u.second]=u.first;
45         for (edge * i=e[u.second];i;i=i->next)
46             q.push(node(min(u.first-i->dist, E[i->point]), i->point));
47     }
48 
49     if (dist[N]==-INF) printf("-1\n");
50     else putint(X+E[N]-(dist[N]<<1));
51 
52     return 0;
53 }
54 inline int getint()
55 {
56     register int num=0;
57     register char ch;
58     do ch=getchar(); while (ch<'0' || ch>'9');
59     do num=num*10+ch-'0', ch=getchar(); while (ch>='0' && ch<='9');
60     return num;
61 }
62 inline void putint(long long num)
63 {
64     char stack[22];
65     register int top=0;
66     if (num==0) stack[top=1]='0';
67     for ( ;num;num/=10) stack[++top]=num%10+'0';
68     for ( ;top;top--) putchar(stack[top]);
69     putchar('\n');
70 }
本傻装B系列

 

posted on 2014-10-29 18:31  dyllalala  阅读(206)  评论(0编辑  收藏  举报