题解:P6961 [NEERC 2017] Journey from Petersburg to Moscow
好像没有严谨证明的题解(可能只是我没有看到),于是我来写一个。
我们假设已经知道第
但是现在我们不知道真正的第
为了方便证明,我们先符号化一下。
按题目中的符号
真实的答案
由
由
综上所述,
用 dijkstra 实现最短路,复杂度为
最后放一下代码。
:::success[code]{open}
#include <bits/stdc++.h>
using namespace std;
const int N=3e3+10;
using ll=long long;
namespace Graph{
struct _edge{
int v,nxt,w;
}es[N*2];
int head[N],gcnt;
using pii=pair<ll,int>;
ll dis[N];
bool vis[N];
priority_queue<pii,vector<pii>,greater<pii> >pq;
void add_edge(int u,int v,int w){
es[++gcnt]={v,head[u],w};head[u]=gcnt;
}
void clear(){
memset(head,0,sizeof head);
gcnt=0;
}
void dijkstra(int s){
memset(dis,0x3f,sizeof dis);
memset(vis,0,sizeof vis);
dis[s]=0;
pq.emplace(0,s);
while(!pq.empty()){
int u=pq.top().second;pq.pop();
if(vis[u]) continue;
vis[u]=1;
for(int i=head[u];i;i=es[i].nxt){
int v=es[i].v;
if(dis[v]>dis[u]+es[i].w){
dis[v]=dis[u]+es[i].w;
pq.emplace(dis[v],v);
}
}
}
}
}
struct edge{
int u,v,w;
}Es[N];
int n,m,K;
int main(){
cin.tie(0)->sync_with_stdio(0);
cin>>n>>m>>K;
for(int i=1;i<=m;i++) cin>>Es[i].u>>Es[i].v>>Es[i].w;
ll ans=0x3ff3f3f3f3f3f3f;
for(int i=0;i<=m;i++){
Graph::clear();
for(int j=1;j<=m;j++){
if(Es[j].w<Es[i].w){
Graph::add_edge(Es[j].u,Es[j].v,0);
Graph::add_edge(Es[j].v,Es[j].u,0);
}else{
Graph::add_edge(Es[j].u,Es[j].v,Es[j].w-Es[i].w);
Graph::add_edge(Es[j].v,Es[j].u,Es[j].w-Es[i].w);
}
}
Graph::dijkstra(1);
ans=min(ans,Graph::dis[n]+1ll*K*Es[i].w);
}
printf("%lld\n",ans);
return 0;
}
:::