L3-028 森森旅游 题解(最短路)
题目链接
题目思路
显然只要正向建边从\(1\)跑最短路,然后反向建边从\(n\)跑最短路
然后答案用\(multiset\)维护即可
注意要判断是否联通,不联通\(cost[i]=INF\)
代码
#include<bits/stdc++.h>
#define fi first
#define se second
#define debug printf("\n I am here\n");
using namespace std;
typedef long long ll;
typedef pair<ll,int> pii;
const int maxn=1e6+5,inf=0x3f3f3f3f,mod=233;
const double eps=1e-6;
const ll INF=0x3f3f3f3f3f3f3f3f;
int n,m,q;
int a[maxn];
int head[maxn],cnt;
ll dis[maxn][3];
struct edge{
int to,next,c,d;
}e[maxn<<2];
ll cost[maxn];
void add(int u,int v,int c,int d){
e[++cnt]={v,head[u],c,d};
head[u]=cnt;
}
void dij(int x,int id){
for(int i=1;i<=n;i++){
dis[i][id]=INF;
}
dis[x][id]=0;
priority_queue<pii,vector<pii>,greater<pii> > que;
que.push({0,x});
while(!que.empty()){
int pos=que.top().se;
ll len=que.top().fi;
que.pop();
if(len!=dis[pos][id]) continue;
for(int i=head[pos];i;i=e[i].next){
int to=e[i].to,w;
if(id==1){
w=e[i].c;
}else{
w=e[i].d;
}
if(dis[to][id]>dis[pos][id]+w){
dis[to][id]=dis[pos][id]+w;
que.push({dis[to][id],to});
}
}
}
}
int u[maxn],v[maxn],c[maxn],d[maxn];
void init(){
cnt=0;
memset(head,0,sizeof(head));
for(int i=1;i<=m;i++){
add(v[i],u[i],c[i],d[i]);
}
}
int main(){
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=m;i++){
scanf("%d%d%d%d",&u[i],&v[i],&c[i],&d[i]);
add(u[i],v[i],c[i],d[i]);
}
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
dij(1,1);
init();
dij(n,2);
multiset<ll> se;
for(int i=1;i<=n;i++){
cost[i]=dis[i][1]+(dis[i][2]+a[i]-1)/a[i];
if(dis[i][1]==INF||dis[i][2]==INF){
cost[i]=INF;
}
se.insert(cost[i]);
}
for(int i=1,x,y;i<=q;i++){
scanf("%d%d",&x,&y);
se.erase(se.lower_bound(cost[x]));
cost[x]=dis[x][1]+(dis[x][2]+y-1)/y;
if(dis[x][1]==INF||dis[x][2]==INF){
cost[x]=INF;
}
se.insert(cost[x]);
ll ans=*(se.begin());
printf("%lld\n",ans);
}
return 0;
}
不摆烂了,写题