Codeforces Round #617 (Div. 3) F. Berland Beauty(LCA+思维)

在这里插入图片描述
在这里插入图片描述
题意:给定一棵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]);
}

发布了70 篇原创文章 · 获赞 0 · 访问量 2438

猜你喜欢

转载自blog.csdn.net/qq_42479630/article/details/104187388