[USACO09JAN] Safe Travel G
题面翻译
【题目描述】
给定一张有 \(n\) 个节点,\(m\) 条边的无向图,对于任意的 \(i\)(\(2\le i\le n\)),请求出在不经过原来 \(1\) 节点到 \(i\) 节点最短路上最后一条边的前提下,\(1\) 节点到 \(i\) 节点的最短路。
特别地,保证 \(1\) 到任何一个点 \(i\) 的最短路都是唯一的。
保证图中没有重边和自环。
【输入格式】
第一行,两个整数 \(n,m\)。
之后 \(m\) 行,每行三个整数 \(a_i,b_i,t_i\) 表示有一条 \(a_i\) 到 \(b_i\),边权为 \(t_i\) 的无向边。
【输出格式】
共 \(n-1\) 行,第 \(i\) 行表示 \(1\) 到 \(i+1\) 在不经过原来 \(1\) 节点到 \(i+1\) 节点最短路上最后一条边的前提下的最短路。如果最短路不存在,则在对应行输出 -1
。
翻译贡献者:@cryozwq。
题目描述
Gremlins have infested the farm. These nasty, ugly fairy-like
creatures thwart the cows as each one walks from the barn (conveniently located at pasture_1) to the other fields, with cow_i traveling to from pasture_1 to pasture_i. Each gremlin is personalized and knows the quickest path that cow_i normally takes to pasture_i. Gremlin_i waits for cow_i in the middle of the final cowpath of the quickest route to pasture_i, hoping to harass cow_i.
Each of the cows, of course, wishes not to be harassed and thus chooses an at least slightly different route from pasture_1 (the barn) to pasture_i.
Compute the best time to traverse each of these new not-quite-quickest routes that enable each cow_i that avoid gremlin_i who is located on the final cowpath of the quickest route from pasture_1 to
pasture_i.
As usual, the M (2 <= M <= 200,000) cowpaths conveniently numbered 1..M are bidirectional and enable travel to all N (3 <= N <= 100,000) pastures conveniently numbered 1..N. Cowpath i connects pastures a_i (1 <= a_i <= N) and b_i (1 <= b_i <= N) and requires t_i (1 <= t_i <= 1,000) time to traverse. No two cowpaths connect the same two pastures, and no path connects a pasture to itself (a_i != b_i). Best of all, the shortest path regularly taken by cow_i from pasture_1 to pasture_i is unique in all the test data supplied to your program.
By way of example, consider these pastures, cowpaths, and [times]:
1--[2]--2-------+
| | |
[2] [1] [3]
| | |
+-------3--[4]--4
TRAVEL BEST ROUTE BEST TIME LAST PATH
p_1 to p_2 1->2 2 1->2
p_1 to p_3 1->3 2 1->3
p_1 to p_4 1->2->4 5 2->4
When gremlins are present:
TRAVEL BEST ROUTE BEST TIME AVOID
p_1 to p_2 1->3->2 3 1->2
p_1 to p_3 1->2->3 3 1->3
p_1 to p_4 1->3->4 6 2->4
For 20% of the test data, N <= 200.
For 50% of the test data, N <= 3000.
TIME LIMIT: 3 Seconds
MEMORY LIMIT: 64 MB
输入格式
* Line 1: Two space-separated integers: N and M
* Lines 2..M+1: Three space-separated integers: a_i, b_i, and t_i
输出格式
* Lines 1..N-1: Line i contains the smallest time required to travel from pasture_1 to pasture_i+1 while avoiding the final cowpath of the shortest path from pasture_1 to pasture_i+1. If no such path exists from pasture_1 to pasture_i+1, output -1 alone on the line.
样例 #1
样例输入 #1
4 5
1 2 2
1 3 2
3 4 4
3 2 1
2 4 3
样例输出 #1
3
3
6
提示
感谢 karlven 提供翻译。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+100;
const ll INF=1e12;
struct edge
{int x,y,n;ll z;bool operator < (const edge &a) const{return z>a.z;}
}e[N<<1];
struct segtree
{struct node{int lc,rc,val;}s[N<<6];int tot;void upd(int &i,ll l,ll r,ll x,int z){if(!i)i=++tot;s[i].val+=z;if(l==r)return ;ll mid=(l+r)>>1;if(x<=mid)upd(s[i].lc,l,mid,x,z);elseupd(s[i].rc,mid+1,r,x,z);}void merg(int &i,int &j,ll l,ll r)//i <-- j{if(i==0 || j==0){i+=j;return ;}if(l==r){s[i].val+=s[j].val;return ;}ll mid=(l+r)>>1;merg(s[i].lc,s[j].lc,l,mid);merg(s[i].rc,s[j].rc,mid+1,r);s[i].val= s[ s[i].lc ].val + s[ s[i].rc ].val;}ll que(int i,ll l,ll r){if(i==0)return 0;if(l==r)return l;ll sum=0;ll mid=(l+r)>>1;if(s[ s[i].lc ].val >0)sum=que(s[i].lc,l,mid);elsesum=que(s[i].rc,mid+1,r);return sum;}
}T;priority_queue<edge ,vector<edge> >q;
vector<int >son[N];
int n,m,head[N],cnt=1,dfn;
int deg[N],vis[N],pre[N],h[N];
int f[N][21],dep[N],root[N],st[N];
ll dis[N],ans[N];
void ad(int x,int y,ll z)
{e[++cnt].n=head[x];e[cnt].y=y;e[cnt].z=z;e[cnt].x=x;head[x]=cnt;
}void init();
void loading();
void work();
void print();
int main()
{init();loading();work();return 0;
}
edge emp;
edge made(int y,ll z)
{emp.y=y;emp.z=z;return emp;
}void dijk()
{++dfn;for(int i=1;i<=n;++i){dis[i]=INF;ans[i]=-1;st[i]=i;}dis[1]=0;q.push( made(1,0) );while(!q.empty()){edge nw=q.top();q.pop();int u=nw.y;if(vis[u]==dfn)continue;vis[u]=dfn;for(int i=head[u],v;i;i=e[i].n){v=e[i].y;if(dis[v]>dis[u]+e[i].z){pre[v]=u;dis[v]=dis[u]+e[i].z;q.push( made(v,dis[v]) );}}}
}void init()
{freopen("travel.in","r",stdin);freopen("travel.out","w",stdout);scanf("%d%d",&n,&m);for(int i=1,x,y;i<=m;++i){ll z;scanf("%d%d%lld",&x,&y,&z);ad(x,y,z);ad(y,x,z);}}int fin(int x)
{return (st[x]==x)?(x):(st[x]=fin(st[x]));
}void go(int u)
{int he=1,ta=0;while(vis[u]<dfn){h[++ta]=u;u=pre[u];}for(int i=ta,fa,x,fx,fy;i>=1;--i){// h[i] --> h[i-1]x=h[i];fa=pre[ x ];fx=fin(x);fy=fin(fa);if(fx!=fy)st[fx]=fy;vis[ x ]=dfn;f[x][0]=fa;dep[x]=dep[fa]+1;++deg[ fa ];son[ fa ].push_back(x);for(int j=1;j<=19;++j)f[x][j]= f[ f[x][j-1] ][j-1];}
}int lca(int x,int y)
{if(x==y)return x;if(dep[x]<dep[y])swap(x,y);for(int i=19;i>=0;--i)if(dep[ f[x][i] ]>dep[y])x=f[x][i];if(dep[x]!=dep[y])x=f[x][0];if(x==y)return x;for(int i=19;i>=0;--i)if(f[x][i] != f[y][i]){x=f[x][i];y=f[y][i];}return f[x][0];
}void loading()
{dijk();++dfn;vis[1]=dfn;for(int i=2;i<=n;++i)if(vis[i]<dfn)go(i);
}void gotans(int u)
{for(int i=0,v;i<deg[u];++i){v=son[u][i];gotans(v);T.merg(root[u],root[v],1ll,INF);}ans[u]=T.que(root[u],1ll,INF)-dis[u];
}void work()
{for(int i=2,x,y,z,lc;i<=cnt;++i){x=e[i].x;y=e[i].y;z=e[i].z;if(f[x][0]==y || f[y][0]==x || ( fin(st[x])!=1 ) || ( fin(st[y])!=1 ) )continue;lc=lca(x,y);//dis[x] + dis[y] +zint val=dis[x] + dis[y] +z;T.upd(root[x],1ll,INF,val,1);T.upd(root[y],1ll,INF,val,1);T.upd(root[lc],1ll,INF,val,-2);}gotans(1);print();
}void print()
{for(int i=2;i<=n;++i){printf("%d\n",(ans[i]<0)?(-1):(ans[i]));}
}