题意
给你一个n个点的树,树有边权
现在有m个限制条件,表示点u到点v路径上的最小值是w
(注意是路径上的最小值,看了好久的题,比如1到3路径最小值是3 假如2到3为3,但是1到2可以为5 满足1到3路径最小值为3! ) 这句话理解清楚了这个题就不是很难了
现在让我们构造这个树的边权,如果不能构造输出-1
思路
因为n只有5000,所以对于每一个限制条件,我们都在路径上保存一下这条边的最大边权,然后我们记录一下这个限制条件中路径上经过的边的编号
最后再check一遍m次限制路径上的边权的最小值是否等于w即可
code
#include<bits/stdc++.h>
#define mst(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
#define endl '\n'
using namespace std;
const int maxn=2e5+5;
int n,m,cnt;
int head[maxn];
struct node{
int v,nex,w;
}e[maxn<<1];
void add_edge(int u,int v,int w){
e[cnt].v=v;
e[cnt].w=w;
e[cnt].nex=head[u];
head[u]=cnt++;
}
int to[maxn],lim[maxn];
int ans[maxn];
vector<int> G[maxn];
void init(){
mst(head,-1);
cnt=0;
for(int i=0;i<=n;i++) G[i].clear();
}
bool dfs(int u,int fa,int id){
if(u==to[id])return true;
for(int i=head[u];~i;i=e[i].nex){
int v=e[i].v;
if(v==fa) continue;
if(dfs(v,u,id)){
int ev=e[i].w;
ans[ev]=max(ans[ev],lim[id]);
G[id].push_back(ev);
return true;
}
}
return false;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
init();
for(int i=1;i<=n-1;i++){
int u,v;
cin>>u>>v;
add_edge(u,v,i);
add_edge(v,u,i);
}
cin>>m;
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
to[i]=v,lim[i]=w;
dfs(u,-1,i);
}
int flag=1;
for(int i=1;i<=m&&flag;i++){
int mmin=inf;
for(auto it:G[i])
mmin=min(mmin,ans[it]);
if(mmin!=lim[i])
flag=0;
}
if(!flag) cout<<-1<<endl;
else{
for(int i=1;i<n;i++)
cout<<max(1,ans[i])<<" ";
cout<<endl;
}
return 0;
}
学如逆水行舟,不进则退