链接
https://pintia.cn/problem-sets/994805342720868352/problems/994805489282433024
题解
这网站上的题经常说不清楚
这题就是从公司出发,遇到的站点如果缺自行车就放下一些,如果有多余的自行车就收着
比如这样一条路径0->1(-5)->2(5),括号里表示需要多少,那么我到达第一个点的时候我就需要5辆自行车,而到2号点的时候我就收集到5辆多余的自行车,答案也就是5 0->1->2 5
做法就是先跑最短路,在跑完最短路的
上做
其实
可以被卡掉的,这样的数据很容易构造
如果想要记忆化,题目又没说数据规模,所以这题本身就很模糊
反正A掉就完了
代码
#include <bits/stdc++.h>
#define maxn 1000010
#define linf (1ll<<60)
#define iinf 0x3f3f3f3f
#define dinf (1e100)
#define cl(x) memset(x,0,sizeof(x))
#define ll long long
using namespace std;
ll C, N, T, M, head[maxn], to[maxn], etot, nex[maxn], w[maxn], dis[maxn], in[maxn], c[maxn], pre[maxn];
stack<ll> anstk, tmp;
pair<ll,ll> ans;
void adde(ll a, ll b, ll c){to[++etot]=b;w[etot]=c;nex[etot]=head[a];head[a]=etot;}
ll read(ll x=0)
{
ll f=1, c;
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-48;
return f*x;
}
void spfa()
{
ll x, p, i;
queue<ll> q;
for(i=1;i<=N;i++)dis[i]=linf;
in[0]=1, q.push(0);
while(!q.empty())
{
x=q.front(), q.pop(), in[x]=0;
for(p=head[x];p;p=nex[p])
if(dis[x]+w[p]<dis[to[p]])
{
dis[to[p]]=dis[x]+w[p];
if(!in[to[p]])q.push(to[p]), in[to[p]]=1;
}
}
}
void dfs(ll pos, ll need, ll spare)
{
ll p, t;
tmp.push(pos);
if(pos==T)
{
if(make_pair(need,spare)<ans)
{
ans=make_pair(need,spare);
anstk=tmp;
}
}
for(p=head[pos];p;p=nex[p])
if(dis[to[p]]==dis[pos]+w[p])
{
t=c[to[p]]-C/2;
if(t>0) dfs(to[p],need,spare+t);
else dfs(to[p],need+max(0ll,-t-spare),max(0ll,spare+t));
}
tmp.pop();
}
void init()
{
ll i, a, b, v;
C=read(), N=read(), T=read(), M=read();
for(i=1;i<=N;i++)c[i]=read();
for(i=1;i<=M;i++)
{
a=read(), b=read(), v=read();
adde(a,b,v), adde(b,a,v);
}
}
void print()
{
printf("%lld ",ans.first);
while(!tmp.empty())tmp.pop();
while(!anstk.empty())tmp.push(anstk.top()), anstk.pop();
while(tmp.size()>1)printf("%lld->",tmp.top()), tmp.pop();
printf("%lld ",tmp.top());
printf("%lld",ans.second);
}
int main()
{
init();
spfa();
ans=make_pair(linf,linf);
dfs(0,0,0);
print();
return 0;
}