[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系列

 

你可能感兴趣的:(OS)