题意:给定一棵n个点的树以及n-1条边,现在给出m组ui,vi,wi,表示ui到vi这条最短路径上的最小边权是wi,要你构造出树的边权。
思路:树上两点的最小边权可以通过lca的方法来遍历求出,关键是怎么构造边权?其实可以把给出的m组条件按从大到小排序,只要保证i点和j点的路径上是权值最大的边先赋值就行。
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e3+1;
const int INF=1e6;
int n,m,num[maxn],size[maxn],ans[maxn],father[maxn],deep[maxn];
struct cxk{
int v,id;
};
struct node{
int u,v,w;
}s[maxn];
vector<cxk>g[maxn];
bool cmp(const node &a,const node &b)
{
return a.w>b.w;
}
void dfs(int u,int fa)
{
father[u]=fa;
deep[u]=deep[fa]+1;
for(auto to:g[u])
{
if(to.v==fa) continue;
dfs(to.v,u);
size[to.v]=to.id;
}
num[u]=INF;
}
bool check(int x,int y,int k)
{
int minn=INF;
if(deep[x]<deep[y]) swap(x,y);
while(deep[x]!=deep[y])
{
if(num[x]==INF) num[x]=k;
minn=min(minn,num[x]);
x=father[x];
}
while(x!=y)
{
if(num[x]==INF) num[x]=k;
minn=min(minn,num[x]);
x=father[x];
if(num[y]==INF) num[y]=k;
minn=min(minn,num[y]);
y=father[y];
}
return minn==k;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<n;++i){
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back({v,i});
g[v].push_back({u,i});
}
dfs(1,0);
scanf("%d",&m);
for(int i=1;i<=m;++i){
int u,v,w;
scanf("%d %d %d",&s[i].u,&s[i].v,&s[i].w);
}
sort(s+1,s+1+m,cmp);
for(int i=1;i<=m;++i){
if(!check(s[i].u,s[i].v,s[i].w)) {
puts("-1");return 0;}
}
for(int i=2;i<=n;++i) ans[size[i]]=num[i];
for(int i=1;i<n;++i) printf("%d ",ans[i]);
}