Description
Gremlins最近在农场上泛滥,它们经常会阻止牛们从农庄(牛棚_1)走到别的牛棚(牛_i的目的地是牛棚_i)。每一个gremlin只认识牛_i并且知道牛_i一般走到牛棚_i的最短路经。所以它们在牛_i到牛棚_i之前的最后一条牛路上等牛_i,当然,牛不愿意遇到Gremlins,所以准备找一条稍微不同的路经从牛棚_1走到牛棚_i,所以,请你为每一头牛_i找出避免gremlin_i的最短路经的长度。
和以往一样,农场上的M (2 <= M <= 200,000)条双向牛路编号为1..M并且能让所有牛到达它们的目的地,N(3 <= N <= 100,000)个编号为1..N的牛棚。牛路i连接牛棚a_i (1 <= a_i <= N)和b_i (1 <= b_i <= N)并且需要时间t_i (1 <=t_i <= 1,000)通过。没有两条牛路连接同样的牛棚,所有牛路满足a_i!=b_i。在所有数据中,牛_i使用的牛棚_1到牛棚_i的最短路经是唯一的。
Input
第一行:两个空格分开的数N和M;
第2..M+1行:三个空格分开的数a_i, b_i,和t_i
Output
第1..N-1行:第i行包含一个数,从牛棚_1到牛棚_i+1并且避免从牛棚1到牛棚i+1最短路经上最后一条牛路的最少的时间。如果这样的路经不存在,输出-1。
Sample Input
4 5
1 2 2
1 3 2
3 4 4
3 2 1
2 4 3
Sample Output
3
3
6
Hint
【数据范围】
20%的数据满足,N<=200;
50%的数据满足,N<=3000
100%的数据满足,N<=100,000
做这道题之前还不知道有最短路径树这个东西。。。(太菜了233)
既然最短路径是唯一的,显然符合树的性质(可以用反证法证最短路性质)。
题目大意:生成最短路径树后,每次fa[x]->x这条边,用剩余所有边来求1->x的最短路径。
发现是个树,首先就想到树剖。。。
对于一个节点x,有ans=min{dist[u]+dist[v]+w(u,v)-dist[x]},x在lca(u,v)之下,在u,v之上(画图),事实上,也只有满足条件的这种x会被更新到:
1、x在v下面,根据最短路径树的性质,dist[u]+w(u,v)+(v->x)>dist[x]所以不会被更新
2、x在u下面,同上
3、x在lca(u,v)上面,显然= =
发现这个性质之后,就是树剖乱搞了。需要注意的是,u,v会被更新,但lca(u,v)不能被更新。
(码了一个晚自习。。。心力憔悴。。。感动。。。)
#include<bits/stdc++.h>
using namespace std;
#define Inc(i,L,r) for(register int i=(L);i<=(r);++i)
#define Red(i,r,L) for(register int i=(r);i>=(L);--i)
const int N = 1e5+10,E = 2e5+10;
struct Edge{
int cnt,h[N],w[E<<1],fr[E<<1],to[E<<1],next[E<<1];
inline void add(int x,int y,int z){
next[++cnt]=h[x],h[x]=cnt;
fr[cnt]=x,to[cnt]=y;
w[cnt]=z;
}
}e,ex;
bool intree[E<<1];
int n,m;
struct Djkstra{
struct Node{
int idx,dist;
bool operator <(const Node&A) const {
return dist>A.dist;
}
};int fa[N],id[N],dist[N];
inline void djkstra(){
memset(dist,63,sizeof(dist));
priority_queue<Node>Q;
Q.push((Node){1,dist[1]=0});
while(!Q.empty()){
Node x=Q.top();Q.pop();
for(int p=e.h[x.idx];p;p=e.next[p]){
int to=e.to[p];if(dist[to]>dist[x.idx]+e.w[p]){
id[to]=p,fa[to]=x.idx;
Q.push((Node){to,dist[to]=dist[x.idx]+e.w[p]});
}
}
}
}
inline void init(){
scanf("%d%d",&n,&m);
e.cnt=1;
Inc(i,1,m){
int x,y,z;scanf("%d%d%d",&x,&y,&z);
e.add(x,y,z),e.add(y,x,z);
}
}
}djk;
struct Graph{
int p[N][18];
inline void init(){
Inc(i,1,n)siz[i]=1;
memset(p,-1,sizeof(p));
Inc(i,2,n)ex.add(djk.fa[i],i,0);
Inc(i,2,n)intree[djk.id[i]]=intree[djk.id[i]^1]=1;//树边
}
int siz[N],son[N],dep[N];
int cnt,dfn[N],top[N];
inline void dfs1(int x,int Fa,int depth){
for(int P=ex.h[x];P;P=ex.next[P]){
dfs1(ex.to[P],p[ex.to[P]][0]=x,dep[ex.to[P]]=depth+1);
siz[x]+=siz[ex.to[P]];
if(siz[son[x]]<siz[ex.to[P]])son[x]=ex.to[P];
}
}
inline void dfs2(int x,int sp){
dfn[x]=++cnt;top[x]=sp;
if(son[x])dfs2(son[x],sp);
for(int P=ex.h[x];P;P=ex.next[P])if((ex.to[P]^p[x][0])&&(ex.to[P]^son[x]))dfs2(ex.to[P],ex.to[P]);
}
inline void ST(){
int maxdep=log2(n);
Inc(j,1,maxdep)
Inc(i,1,n)if(~p[i][j-1])p[i][j]=p[p[i][j-1]][j-1];
}
inline int lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
Red(i,log2(dep[x]),0)if(dep[x]-(1<<i)>=dep[y])x=p[x][i];
if(x==y)return y;
Red(i,log2(dep[x]),0)if(p[x][i]^p[y][i])x=p[x][i],y=p[y][i];
return p[x][0];
}
}g;
struct SegMent{
struct tree{
int L,r,mn;
}t[N<<2];
#define Ls v<<1
#define rs v<<1|1
inline void pushdown(int v){
t[Ls].mn=min(t[Ls].mn,t[v].mn);
t[rs].mn=min(t[rs].mn,t[v].mn);
}
inline int query(int v,int x){
if(t[v].L>x||t[v].r<x)return 1<<30;
if(t[v].L==t[v].r)return t[v].mn;
pushdown(v);
return min(query(Ls,x),query(rs,x));
}
inline void update(int v,int A,int b,int k){
if(t[v].L>b||t[v].r<A)return ;
if(A<=t[v].L&&t[v].r<=b)return t[v].mn=min(t[v].mn,k),void();
pushdown(v);
update(Ls,A,b,k),update(rs,A,b,k);
}
inline void build(int v,int L,int r){
t[v]=(tree){L,r,1<<30};
if(L==r)return ;
int Mid=L+r>>1;
build(Ls,L,Mid),build(rs,Mid+1,r);
}
}t;
inline void modify(int x,int lca,int val){
int tx=g.top[x];
while(tx^g.top[lca]){
t.update(1,g.dfn[tx],g.dfn[x],val);
x=g.p[tx][0],tx=g.top[x];
}
t.update(1,g.dfn[lca]+1,g.dfn[x],val);
}
inline void solv(){
t.build(1,1,n);
Inc(i,2,e.cnt)if(!intree[i]){
int x=e.fr[i],y=e.to[i],lca=g.lca(x,y);
modify(x,lca,djk.dist[x]+djk.dist[y]+e.w[i]);
modify(y,lca,djk.dist[x]+djk.dist[y]+e.w[i]);
}
Inc(i,2,n){
int dist=t.query(1,g.dfn[i]);
cout<<(dist==1<<30?-1:dist-djk.dist[i])<<"\n";
}
}
int main(){
djk.init();
djk.djkstra();
g.init();
g.dfs1(1,0,0);
g.dfs2(1,1);
g.ST();
solv();
return 0;
}