[vijos P1880]ファーラの力

时间:2023-03-09 02:40:42
[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[终点]

 #include <cstdio>
#include <queue>
#include <algorithm>
typedef std::pair<long long, int> node;
const long long INF=0x7FFFFFFFFFFFFFLL;
const int sizeOfPoint=;
const int sizeOfEdge=; struct edge {int point, dist; edge * next;};
edge memory[sizeOfEdge], * port=memory;
edge * e[sizeOfPoint];
inline edge * newedge(int point, int dist, edge * next)
{
edge * ret=port++;
ret->point=point; ret->dist=dist; ret->next=next;
return ret;
} int N, M, X;
int E[sizeOfPoint];
long long dist[sizeOfPoint];
std::priority_queue<node> q;
inline long long min(long long x, long long y) {return x<y?x:y;}
inline int getint();
inline void putint(long long); int main()
{
N=getint(), M=getint(), X=getint();
for (int i=;i<=N;i++) E[i]=getint();
for (int i=;i<M;i++)
{
int A, B, T;
A=getint(), B=getint(), T=getint();
if (E[A]>=T) e[A]=newedge(B, T, e[A]);
if (E[B]>=T) e[B]=newedge(A, T, e[B]);
} for (int i=;i<=N;i++) dist[i]=-INF;
for (q.push(node(X, ));!q.empty(); )
{
node u=q.top(); q.pop();
if (dist[u.second]!=-INF) continue;
dist[u.second]=u.first;
for (edge * i=e[u.second];i;i=i->next)
q.push(node(min(u.first-i->dist, E[i->point]), i->point));
} if (dist[N]==-INF) printf("-1\n");
else putint(X+E[N]-(dist[N]<<)); return ;
}
inline int getint()
{
register int num=;
register char ch;
do ch=getchar(); while (ch<'' || ch>'');
do num=num*+ch-'', ch=getchar(); while (ch>='' && ch<='');
return num;
}
inline void putint(long long num)
{
char stack[];
register int top=;
if (num==) stack[top=]='';
for ( ;num;num/=) stack[++top]=num%+'';
for ( ;top;top--) putchar(stack[top]);
putchar('\n');
}

本傻装B系列