trick:
通过h存正图和反图
不一定所有点都可以到达终点
multiset的删除
error:
段错误的一个可能性:ll的运算用int存
#include<bits/stdc++.h>
//正图和反图,用head来区分即可
//指针不可以读sizeof
//忘了判断联通性了,不一定可以通过某个点去到终点
//删除multiset的时候的先find再删除
//段错误的一个可能性:ll写成了int
using namespace std;
using pii = pair<long long,int>;
using ll = long long;
const int N = 1e5+5;
const int M =4e5+3;
int n,m,q;
int e[M],nex[M],cnt;
ll w[M];
int h1[N],h2[N];
ll aa[N];
void add(int *head,int a,int b,ll c)
{
e[cnt]=b,w[cnt]=c,nex[cnt]=head[a],head[a]=cnt++;
}
bool repeat[N];
ll dist1[N],dist2[N];
void dijkstra(ll *dist,int *head,int tttop)
{
//sizeof dist返回指针大小,不要搞错了
// memset(dist,0x3f,sizeof dist);
memset(dist,0x3f,sizeof dist1);
memset(repeat,0,sizeof repeat);
multiset<pii> sset;
dist[tttop]=0;
sset.insert(make_pair(0,tttop));
while(sset.size())
{
auto ttop=*(sset.begin());
auto it = sset.begin();
sset.erase(it);
int u=ttop.second;
if(repeat[u])continue;
repeat[u]=true;
for(int i=head[u];i!=-1;i=nex[i])
{
int v=e[i];
ll w2=w[i];
if(dist[v]>dist[u]+w2)
{
dist[v]=dist[u]+w2;
sset.insert(make_pair(dist[v],v));
}
}
}
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>m>>q;
memset(h1,-1,sizeof h1);
memset(h2,-1,sizeof h2);
for(int i=1;i<=m;i++)
{
int u,v,c,d;
cin>>u>>v>>c>>d;
add(h1,u,v,c);
add(h2,v,u,d);
}
multiset<ll> val;
dijkstra(dist1,h1,1);
dijkstra(dist2,h2,n);
for(int v=1;v<=n;v++)
{
cin>>aa[v];
//当前点兑换的最小金额数就是dist1[i]+ceil(dist2[i]/a[i]);
if(dist1[v]!=0x3f3f3f3f3f3f3f3fll&&dist2[v]!=0x3f3f3f3f3f3f3f3fll)
{
//这里写成了int会导致段错误
ll temp_val=dist1[v]+(dist2[v]+aa[v]-1)/aa[v];
val.insert(temp_val);
}
}
while(q--){
int v;
ll www;
cin>>v>>www;
if(dist1[v]!=0x3f3f3f3f3f3f3f3fll&&dist2[v]!=0x3f3f3f3f3f3f3f3fll)
{
auto era=val.find(dist1[v]+(dist2[v]+aa[v]-1)/aa[v]);
val.erase(era);
}
aa[v]=www;
if(dist1[v]!=0x3f3f3f3f3f3f3f3fll&&dist2[v]!=0x3f3f3f3f3f3f3f3fll)
val.insert(1ll*dist1[v]+1ll*(dist2[v]+aa[v]-1)/aa[v]);
cout<<(*(val.begin()))<<endl;
}
return 0;
}