题解
-
显然只会走一条非树边
-
我们枚举一条非树边,能够以这条边为答案的树边一定在非树边两端点的路径上
-
注意到区间取max取min非常难写于是我们可以对非树边排序,从大到小排序,那么每次就直接覆盖就好了,因为每次只会最优
-
可以用并查集,我们加树边等价于把两端点到它们lca路径上的边缩起来,表明这些边不会再更新答案了
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <queue> 4 #include <cstring> 5 #include <algorithm> 6 #define N 100010 7 using namespace std; 8 struct edge{int to,from,w;}e[N*2]; 9 struct node{int x,y,v;}Q[N]; 10 int n,m,cnt,fa[N],dep[N],k[N],d[N],p[N],head[N],father[N]; 11 void insert(int x,int y,int z) { e[++cnt].to=y; e[cnt].from=head[x]; e[cnt].w=z; head[x]=cnt; } 12 int getfather(int x) { return father[x]?father[x]=getfather(father[x]):x; } 13 void dfs(int x,int pre) 14 { 15 fa[x]=pre,dep[x]=dep[pre]+1; 16 for (int i=head[x];i;i=e[i].from) if (e[i].to!=pre) p[e[i].to]=e[i].w,dfs(e[i].to,x); 17 } 18 void work(int &x,int y) { d[p[x]]=y,father[x]=getfather(fa[x]),x=father[x]; } 19 bool cmp(node a,node b) { return a.v<b.v; } 20 int main() 21 { 22 freopen("worry.in","r",stdin),freopen("worry.out","w",stdout); 23 scanf("%d%d",&n,&m); 24 for (int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),insert(x,y,i),insert(y,x,i),d[i]=-1; 25 for (int i=1,x,y,z;i<=m;i++) scanf("%d%d%d",&Q[i].x,&Q[i].y,&Q[i].v); 26 dfs(1,0),sort(Q+1,Q+m+1,cmp); 27 for (int i=1;i<=m;i++) 28 { 29 int x=getfather(Q[i].x),y=getfather(Q[i].y); 30 while (x!=y) work(dep[x]<dep[y]?y:x,Q[i].v); 31 } 32 for (int i=1;i<n;i++) printf("%d ",d[i]); 33 }