Description
题解
复习一下树链剖分。
最短路树,非树边与树边形成的环上,除了LCA,其他的点都可以经过非树边,从所有答案中刷最小值,用树链剖分维护。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define maxn 100006
#define maxe 200006
using namespace std;
inline char nc(){
static char buf[100000],*i=buf,*j=buf;
return i==j&&(j=(i=buf)+fread(buf,1,100000,stdin),i==j)?EOF:*i++;
}
inline int _read(){
char ch=nc();int sum=0;
while(!(ch>='0'&&ch<='9'))ch=nc();
while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();
return sum;
}
int n,e,N,tem,tot[2],dep[maxn],id[maxn],dis[maxn],fa[maxn],top[maxn],num[maxn],H_son[maxn],
lnk[2][maxn],son[2][maxe*2],nxt[2][maxe*2],w[2][maxe*2];
bool vis[maxn];
struct point{
int x,s;
bool operator <(const point&b)const{return s>b.s;}
};
priority_queue <point > heap;
struct side{
int x,y,w;
}a[maxe];
struct data{
int l,r,tag,x;
void add(int k){
tag=min(tag,k);x=min(x,k);
}
}tree[maxn*4];
void add(int p,int x,int y,int z){
nxt[p][++tot[p]]=lnk[p][x];son[p][tot[p]]=y;w[p][tot[p]]=z;lnk[p][x]=tot[p];
}
void dij(){
memset(vis,1,sizeof(vis));memset(dis,63,sizeof(dis));
dis[1]=0;point p;p.x=1;p.s=0;heap.push(p);
for(int i=1;i<=n;i++){
while(!vis[heap.top().x])heap.pop();
p=heap.top();heap.pop();
vis[p.x]=0;
for(int j=lnk[0][p.x];j;j=nxt[0][j]) if(vis[son[0][j]]&&dis[p.x]+w[0][j]<dis[son[0][j]]){
dis[son[0][j]]=dis[p.x]+w[0][j];fa[son[0][j]]=p.x;
point pp;pp.x=son[0][j];pp.s=dis[son[0][j]];heap.push(pp);
}
}
for(int i=2;i<=n;i++)add(1,fa[i],i,0);
}
void dfs1(int x){
vis[x]=0;num[x]=1;
for(int j=lnk[1][x];j;j=nxt[1][j]) if(vis[son[1][j]]){
dep[son[1][j]]=dep[x]+1;
dfs1(son[1][j]);
if(num[son[1][j]]>num[H_son[x]])H_son[x]=son[1][j];
num[x]+=num[son[1][j]];
}
}
void build(int p,int l,int r){
tree[p].l=l;tree[p].r=r;tree[p].tag=tree[p].x=1e9;
if(l>=r)return;
int mid=(l+r)>>1;
build(p<<1,l,mid);build(p<<1|1,mid+1,r);
}
void pushdown(int p){
if(tree[p].tag==1e9)return;
tree[p<<1].add(tree[p].tag);tree[p<<1|1].add(tree[p].tag);
tree[p].tag=1e9;
}
void update(int p,int l,int r,int k){
if(tree[p].l>r||tree[p].r<l)return;
if(l<=tree[p].l&&r>=tree[p].r){
tree[p].add(k);return;
}
pushdown(p);
update(p<<1,l,r,k);update(p<<1|1,l,r,k);
tree[p].x=min(tree[p<<1].x,tree[p<<1|1].x);
}
int query(int p,int k){
if(tree[p].l>k||tree[p].r<k)return 1e9;
if(tree[p].l==tree[p].r)return tree[p].x;
pushdown(p);
return min(query(p<<1,k),query(p<<1|1,k));
}
void dfs2(int x,int y){
vis[x]=0;id[x]=++tem;top[x]=y;
if(H_son[x]){
fa[H_son[x]]=x;
dfs2(H_son[x],y);
}
for(int j=lnk[1][x];j;j=nxt[1][j])if(vis[son[1][j]]){
fa[son[1][j]]=x;
dfs2(son[1][j],son[1][j]);
}
}
void change(int x,int y,int k){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
update(1,id[top[x]],id[x],k);
x=fa[top[x]];
}
if(x==y)return;
if(dep[x]>dep[y])swap(x,y);
update(1,id[H_son[x]],id[y],k);
}
int main(){
freopen("travel.in","r",stdin);
freopen("travel.out","w",stdout);
n=_read();e=_read();
for(int i=1,x,y,z;i<=e;i++)x=_read(),y=_read(),z=_read(),add(0,x,y,z),add(0,y,x,z);
dij();
for(int i=1;i<=n;i++)
for(int j=lnk[0][i];j;j=nxt[0][j]) if((j&1)&&fa[i]!=son[0][j]&&fa[son[0][j]]!=i){
++N;a[N].x=i;a[N].y=son[0][j];a[N].w=w[0][j]+dis[a[N].x]+dis[a[N].y];
}
memset(vis,1,sizeof(vis));dep[1]=1;
dfs1(1);
memset(vis,1,sizeof(vis));
build(1,1,n);dfs2(1,1);
for(int i=1;i<=N;i++)change(a[i].x,a[i].y,a[i].w);
for(int i=2;i<=n;i++){
int t=query(1,id[i]);
if(t==1e9)printf("-1\n");
else printf("%d\n",t-dis[i]);
}
return 0;
}