神题Orz。
我们可以先dijkstra求出最短路径树。然后有一些不在树上的边,加入后一定会形成一个环,那么此时就为一些点提供了次短路径。
假设我们加入了一条边(u,v),令t=lca(u,v),对于在链t->v上的点x,我们可以走这样一条路线:1->t->u->v->x,画个图可以发现,此时的长度为dis[u]+len(u,v)+dis[v]-dis[x]。dix[x]是已知的,要使结果最小,我们就要使dis[u]+len(u,v)+dis[v]最小。
然后我们可以用树链剖分和线段树来维护一下这个最小值。
#include<iostream>
#include<cstdio>
#define inf 1000000007
#define N 100005
using namespace std;
int n,m,cnt,sz,dfn;
int head[N],dis[N],from[N],belong[N],deep[N],size[N],id[N],fa[N][20];
int u[N<<1],v[N<<1],w[N<<1];
bool vis[N],mark[N<<2];
int next[N<<2],list[N<<2],key[N<<2],tag[N<<2],l[N<<2],r[N<<2];
struct node {int v,id;} heap[N];
inline int read()
{
int a=0,f=1; char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
return a*f;
}
inline void insert(int x,int y,int z)
{
next[++cnt]=head[x];
head[x]=cnt;
list[cnt]=y;
key[cnt]=z;
}
inline void push(node x)
{
heap[++sz]=x;
int now=sz;
while (now&&heap[now].v<heap[now>>1].v)
{
swap(heap[now],heap[now>>1]);
now>>=1;
}
}
inline void pop()
{
heap[1]=heap[sz--];
int now=1;
while (now<=(sz>>1))
{
int next=now<<1;
if (next<sz&&heap[next].v>heap[next+1].v) next++;
if (heap[now].v<heap[next].v) return;
swap(heap[now],heap[next]);
now=next;
}
}
inline void dijkstra()
{
for (int i=1;i<=n;i++) dis[i]=inf;
dis[1]=0;
push((node){0,1});
while (sz)
{
int x=heap[1].id; pop();
if (vis[x]) continue; vis[x]=1;
for (int i=head[x];i;i=next[i])
if (dis[list[i]]>dis[x]+key[i])
{
dis[list[i]]=dis[x]+key[i];
mark[from[list[i]]]=0;
from[list[i]]=i;
mark[i]=1;
push((node){dis[list[i]],list[i]});
}
}
}
void dfs1(int x)
{
for (int i=1;(1<<i)<=deep[x];i++) fa[x][i]=fa[fa[x][i-1]][i-1];
size[x]=1;
for (int i=head[x];i;i=next[i])
if (mark[i])
{
fa[list[i]][0]=x;
deep[list[i]]=deep[x]+1;
dfs1(list[i]);
size[x]+=size[list[i]];
}
}
void dfs2(int x,int chain)
{
id[x]=++dfn; belong[x]=chain;
int k=0;
for (int i=head[x];i;i=next[i])
if (mark[i]&&size[list[i]]>size[k]) k=list[i];
if (!k) return;
dfs2(k,chain);
for (int i=head[x];i;i=next[i])
if (mark[i]&&list[i]!=k) dfs2(list[i],list[i]);
}
inline int lca(int x,int y)
{
if (deep[x]<deep[y]) swap(x,y);
int t=deep[x]-deep[y];
for (int i=0;(1<<i)<=t;i++)
if ((1<<i)&t) x=fa[x][i];
for (int i=19;i>=0;i--)
if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return x==y?x:fa[x][0];
}
void build(int k,int x,int y)
{
l[k]=x; r[k]=y; tag[k]=inf;
if (l[k]==r[k]) return;
int mid=l[k]+r[k]>>1;
build(k<<1,x,mid); build(k<<1|1,mid+1,y);
}
inline void pushdown(int k)
{
if (l[k]==r[k]|tag[k]==inf) return;
tag[k<<1]=min(tag[k<<1],tag[k]);
tag[k<<1|1]=min(tag[k<<1|1],tag[k]);
tag[k]=inf;
}
void change(int k,int x,int y,int v)
{
pushdown(k);
if (x==l[k]&&r[k]==y)
{
tag[k]=min(tag[k],v);
return;
}
int mid=l[k]+r[k]>>1;
if (y<=mid) change(k<<1,x,y,v);
else if (x>mid) change(k<<1|1,x,y,v);
else change(k<<1,x,mid,v),change(k<<1|1,mid+1,y,v);
}
inline void solve_change(int x,int f,int v)
{
while (belong[x]!=belong[f])
{
change(1,id[belong[x]],id[x],v);
x=fa[belong[x]][0];
}
if (x!=f) change(1,id[f]+1,id[x],v);
}
int query(int k,int x)
{
pushdown(k);
if (l[k]==r[k]) return tag[k];
int mid=l[k]+r[k]>>1;
if (x<=mid) return query(k<<1,x);
else return query(k<<1|1,x);
}
int main()
{
n=read(); m=read();
for (int i=1;i<=m;i++)
u[i]=read(),v[i]=read(),w[i]=read(),insert(u[i],v[i],w[i]),insert(v[i],u[i],w[i]);
dijkstra();
dfs1(1);
dfs2(1,1);
build(1,1,n);
for (int i=1;i<=m;i++)
{
int t=lca(u[i],v[i]);
if (!mark[2*i-1]) solve_change(v[i],t,dis[u[i]]+dis[v[i]]+w[i]);
if (!mark[2*i]) solve_change(u[i],t,dis[u[i]]+dis[v[i]]+w[i]);
}
for (int i=2;i<=n;i++)
{
int t=query(1,id[i]);
if (t==inf) puts("-1"); else printf("%d\n",t-dis[i]);
}
return 0;
}