Description
江湖由 N 个门派(2≤N≤100,000,编号从 1 到 N)组成,这些门派之间有 N-1 条小道将他们连接起来,每条道路都以“尺”为单位去计量,武林盟主发现任何两个门派都能够直接或者间接通过小道连接。
虽然整个江湖是可以互相到达的,但是他担心有心怀不轨之徒破坏这个武林的安定,破坏小道,于是武林盟主又秘密地修建了 M 条密道(1≤M≤100,000),但每条小道距离都不超过10亿尺。
果不其然,最近一个名叫“太吾”的组织意欲破坏武林的小道,请你帮盟主想想办法,如果门派 A 到门派 B 的直连小道被破坏,从 A 走到 B 的所有路径中,经过密道的距离最少是多少?
Input
第一行数字 N M
接下来 N-1 行,每行两个整数 A B,表示 A-B 间有一条直连小道
接下来 M 行,每行三个数字 A B V,表示 A-B 间有一条代价为 V 的密道
Output
输出 N-1 行,对应原输入的小道,每个小道被破坏后,最少需要经过多长的密道?如果不存在替换的道路,请输出-1
Sample Input
6 3 4 1 1 3 4 5 1 2 6 5 3 6 8 2 3 7 6 4 5
Sample Output
8 7 5 7 5
Data Constraint
30%数据:N<=300,M<=1000
50%数据:N<=1000,M<=1000
70%数据:N<=5000,M<=5000
对于另外15%的数据点:树是一条链
100%数据:N,M<=100,000
分析
这题显然密道会密道两端到LCA中经过的边的值
这不就是树链剖分嘛
写个区间修改走人
什么?并查集做法?不会
#include <iostream> #include <cstdio> #include <cstring> #define rep(i,a,b) for (i=a;i<=b;i++) using namespace std; const int N=1e5+10; struct Node { int sz,f,s,seg,top,dep; }a[N]; int scnt,rev[N]; struct Edge { int u,v,nx; }g[2*N]; int cnt,list[N]; int t[4*N],lz[4*N]; int mn; int n,m; void Add(int u,int v) {g[++cnt].u=u;g[cnt].v=v;g[cnt].nx=list[u];list[u]=cnt;} void Dfs1(int x,int f) { a[x].f=f;a[x].dep=a[f].dep+1;a[x].sz=1; for (int i=list[x];i;i=g[i].nx) if (g[i].v!=f) { Dfs1(g[i].v,x); a[x].sz+=a[g[i].v].sz; if (a[g[i].v].sz>a[a[x].s].sz) a[x].s=g[i].v; } } void Dfs2(int x,int f) { int son=a[x].s; if (son) { a[son].seg=++scnt; rev[scnt]=son; a[son].top=a[x].top; Dfs2(son,x); } for (int i=list[x];i;i=g[i].nx) if (!a[g[i].v].top) { a[g[i].v].seg=++scnt; rev[scnt]=g[i].v; a[g[i].v].top=g[i].v; Dfs2(g[i].v,x); } } void Build(int x,int l,int r) { if (l==r) { t[x]=2147483647; return; } int mid=l+r>>1; Build(x<<1,l,mid);Build((x<<1)+1,mid+1,r); t[x]=2147483647; } void Pushdown(int x) { if (lz[x]) { t[x<<1]=lz[x<<1]=min(!lz[x<<1]?2147483647:lz[x<<1],lz[x]); t[(x<<1)+1]=lz[(x<<1)+1]=min(!lz[(x<<1)+1]?2147483647:lz[(x<<1)+1],lz[x]); lz[x]=0; } } void Change_In_Segment(int x,int l,int r,int val,int ll,int rr) { if (ll>rr) return; if (l>rr||ll>r) return; if (ll<=l&&r<=rr) { t[x]=min(t[x],val); lz[x]=min(!lz[x]?2147483647:lz[x],val); return; } Pushdown(x); int mid=l+r>>1; if (mid>=ll) Change_In_Segment(x<<1,l,mid,val,ll,rr); if (mid<rr) Change_In_Segment((x<<1)+1,mid+1,r,val,ll,rr); t[x]=min(t[x<<1],t[(x<<1)+1]); } void Query_In_Segment(int x,int l,int r,int ll,int rr) { if (ll>rr) return; if (r<ll||l>rr) return; if (ll<=l&&r<=rr) { mn=min(mn,t[x]); return; } Pushdown(x); int mid=l+r>>1; if (ll<=mid) Query_In_Segment(x<<1,l,mid,ll,rr); if (mid+1<=rr) Query_In_Segment((x<<1)+1,mid+1,r,ll,rr); } void Query_In_Tree(int x,int y) { int fx=a[x].top,fy=a[y].top; while (fx!=fy) { if (a[fx].dep<a[fy].dep) swap(x,y),swap(fx,fy); Query_In_Segment(1,1,scnt,a[fx].seg,a[x].seg); x=a[fx].f;fx=a[x].top; } if (a[x].dep>a[y].dep) swap(x,y); Query_In_Segment(1,1,scnt,a[x].seg+1,a[y].seg); } void Change_In_Tree(int x,int y,int val) { int fx=a[x].top,fy=a[y].top; while (fx!=fy) { if (a[fx].dep<a[fy].dep) swap(x,y),swap(fx,fy); Change_In_Segment(1,1,scnt,val,a[fx].seg,a[x].seg); x=a[fx].f;fx=a[x].top; } if (a[x].dep>a[y].dep) swap(x,y); Change_In_Segment(1,1,scnt,val,a[x].seg+1,a[y].seg); } int main() { freopen("worry.in","r",stdin); freopen("worry.out","w",stdout); int i; char s[20]; scanf("%d%d",&n,&m); rep(i,1,n-1) { int u,v; scanf("%d%d",&u,&v); Add(u,v);Add(v,u); } Dfs1(1,0); scnt=1; a[1].seg=a[1].top=rev[1]=1; Dfs2(1,0); Build(1,1,scnt); for (int i=1;i<=m;i++) { int x,y,w; scanf("%d%d%d",&x,&y,&w); Change_In_Tree(x,y,w); } for (int i=1;i<=n-1;i++) { mn=2147483647; Query_In_Tree(g[i*2-1].u,g[i*2-1].v); printf("%d\n",mn==2147483647?-1:mn); } }
原文地址:https://www.cnblogs.com/mastervan/p/9818585.html
时间: 2024-10-05 03:10:02