本文编写于 1298 天前,最后修改于 1298 天前,其中某些信息可能已经过时。
题目链接:
https://pintia.cn/problem-sets/994805046380707840/problems/1386335159927652364
题解:
建两个图,正图和反图。
正图里的边权是现金,反图里的边权是旅游金。
然后分别以1为起点在正图上跑最短路,以n为起点在反图上跑最短路。
这样计算出每个点的答案,取最小,不带修改的情况就做完了。
带修改的情况放线段树上维护一下就好了。
注意巨大坑点:不保证图连通。
参考链接:
https://www.cnblogs.com/zhanglichen/p/14726600.html
代码:
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
struct node
{
ll to,val;
};
vector<node>v_mon[200500],v_bi[200500];
ll a[200500]= {0};
struct node1
{
ll now,val;
bool operator <(const node1& a) const
{
return val>a.val;
}
};
priority_queue<node1>que1,que2;
ll dis_mon[200500]= {0},dis_bi[200500]= {0};
ll tree[800500]= {0};
ll min1[800500]= {0};
ll val[800500]= {0};
void push_up(ll n)
{
min1[n]=min(min1[2*n],min1[2*n+1]);
}
void build(ll n,ll l,ll r)
{
if(l==r)
{
min1[n]=tree[n]=val[l];
return ;
}
ll mid=(l+r)/2;
build(2*n,l,mid);
build(2*n+1,mid+1,r);
push_up(n);
}
void update(ll n,ll L,ll R,ll pos,ll val1)
{
if(L==R&&L==pos)
{
min1[n]=tree[n]=val1;
return ;
}
ll mid=(L+R)/2;
if(pos<=mid)
update(2*n,L,mid,pos,val1);
else
update(2*n+1,mid+1,R,pos,val1);
push_up(n);
}
int main()
{
ll n,m,k,from,to,val1,val2,pos;
scanf("%lld%lld%lld",&n,&m,&k);
for(ll i=1; i<=n; i++)
dis_mon[i]=inf,dis_bi[i]=inf;
dis_mon[1]=0,dis_bi[n]=0;
for(ll i=1; i<=m; i++)
{
scanf("%lld%lld%lld%lld",&from,&to,&val1,&val2);
v_mon[from].push_back({to,val1});
v_bi[to].push_back({from,val2});
}
que1.push({1,0});
while(!que1.empty())
{
ll now=que1.top().now,val=que1.top().val;
que1.pop();
for(node i:v_mon[now])
{
if(dis_mon[i.to]>val+i.val)
{
dis_mon[i.to]=val+i.val;
que1.push({i.to,dis_mon[i.to]});
}
}
}
que2.push({n,0});
while(!que2.empty())
{
ll now=que2.top().now,val=que2.top().val;
que2.pop();
for(node i:v_bi[now])
{
if(dis_bi[i.to]>val+i.val)
{
dis_bi[i.to]=val+i.val;
que2.push({i.to,dis_bi[i.to]});
}
}
}
for(ll i=1; i<=n; i++)
scanf("%lld",&a[i]);
for(ll i=1; i<=n; i++)
{
if(dis_mon[i]==inf||dis_bi[i]==inf)
val[i]=inf;
else
val[i]=dis_mon[i]+dis_bi[i]/a[i]+(ll)((dis_bi[i]%a[i])>0?1:0);
}
build(1,1,n);
for(ll i=1; i<=k; i++)
{
scanf("%lld",&pos);
scanf("%lld",&a[pos]);
if(dis_mon[pos]==inf||dis_bi[pos]==inf)
val[pos]=inf;
else
val[pos]=dis_mon[pos]+dis_bi[pos]/a[pos]+(ll)((dis_bi[pos]%a[pos])>0?1:0);
update(1,1,n,pos,val[pos]);
printf("%lld\n",min1[1]);
}
}