版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/83552046
传送门
解析:
首先,这道题没有负边权,写 的不是想乱搞过题就是压根不会 。然而真的有人乱搞过了题。。。然后在 上又被新数据卡 了。
思路:
直接建边显然是 ,跑最短路就是 ,肯定会gg。
考虑优化建图。
首先对于原题中路径的定义,考虑重新处理。将每个点的贡献变成进入它的边的权值+在入边意义下出边的贡献。
所以这样可以化边为点。
将每个点所有出边取出来,排个序,大的边向小的边连权值为
的边,表示在入边是大边的情况下,出边的贡献是0。小的依次向它的后继连权值为权值之差的边,表示如果走这条边出去,新增的贡献是差量。
然后所有边的反向边向它连权值为原权值的边,表示进入这个点之后要出去需要先计算它作为下一个点入边的代价。
这样建出来的边的规模就是 ,最多不会超过 条边。
之后直接 跑一下最短路,在终点的所有出边的反向边处考虑新的权值
代码(截止博客完工时,这份代码全OJ时空都是rank1,空间只有rank2的一半):
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
return num;
}
cs int N=200005;
int last[N],nxt[N<<1],to[N<<1],ecnt=1;
int w[N<<1];
inline void addedge(int u,int v,int val){
nxt[++ecnt]=last[u],last[u]=ecnt,to[ecnt]=v,w[ecnt]=val;
nxt[++ecnt]=last[v],last[v]=ecnt,to[ecnt]=u,w[ecnt]=val;
}
namespace NEWGRAPH{
int last[N<<1],nxt[N*6],to[N*6],ecnt;
int w[N*6];
inline void addedge(int u,int v,int val){
nxt[++ecnt]=last[u],last[u]=ecnt,to[ecnt]=v,w[ecnt]=val;
}
ll dist[N<<1];
bool vis[N<<1];
priority_queue<pair<ll,int> ,vector<pair<ll,int> > ,greater<pair<ll,int> > > q;
inline void Dijkstra(){
memset(dist,0x3f,sizeof dist);
for(int re e=::last[1],v=::to[e];e;v=::to[e=::nxt[e]]){
dist[e]=::w[e];
q.push(make_pair(dist[e],e));
}
while(!q.empty()){
int u=q.top().second;q.pop();
if(vis[u])continue;
vis[u]=true;
for(int re e=last[u],v=to[e];e;v=to[e=nxt[e]]){
if(dist[v]>dist[u]+w[e]){
dist[v]=dist[u]+w[e];
q.push(make_pair(dist[v],v));
}
}
}
}
}
int n,m;
signed main(){
n=getint();
m=getint();
for(int re i=1;i<=m;++i){
int u=getint(),v=getint(),val=getint();
addedge(u,v,val);
}
for(int re u=1;u<=n;++u){
vector<pair<int,int> > q;
for(int re e=last[u],v=to[e];e;v=to[e=nxt[e]])
q.push_back(make_pair(w[e],e));
sort(q.begin(),q.end());
for(int re i=0;i<q.size();++i){
if(i)NEWGRAPH::addedge(q[i].second,q[i-1].second,0);
if(i+1<q.size())NEWGRAPH::addedge(q[i].second,q[i+1].second,q[i+1].first-q[i].first);
NEWGRAPH::addedge(q[i].second^1,q[i].second,q[i].first);
}
}
NEWGRAPH::Dijkstra();
ll SP=0x3f3f3f3f3f3f3f3f;
for(int re e=last[n];e;e=nxt[e]){
SP=min(SP,NEWGRAPH::dist[e^1]+w[e]);
}
cout<<SP;
return 0;
}