https://vjudge.net/problem/CodeForces-1296F
题目大意:给出一棵有
个节点的无根树,对于
个询问
满足从
到
的路径上的边权的最小值是
,如果可以满足的话输出
条边的权值,要求
,否则输出
。
思路:虽然是 题,其实就是一个裸的暴力。依次处理 个询问,找到从 到 的路径,然后把该路径上的边的权值取本身与 的最大值。然后再遍历一遍 个询问,看 到 的路径上的边权的最小值是否等于 ,若相等则说明有解,输出每条边的边权即可( 可以改成范围内的任意一个值)。树上找任意两点的路径也比较简单,这里提供两种方法:(1)暴力,用二维数组 表示以 为根时 的父节点,一共需要 次 ,复杂度 ;(2)用 表示以 为根时 的父节点,只需 次 ,但是求路径时需要求 ,因此复杂度为 。以下代码采取第一种方法(懒得写第二种 )。总复杂度 。
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=5005;
struct Edge
{
int to,nxt;
}edge[maxn<<1];
int n,m,tot,root;
int head[maxn];
int x[maxn],y[maxn],fa[maxn][maxn],ans[maxn][maxn];
int u[maxn],v[maxn],d[maxn];
inline void addedge(int u,int v)
{
edge[++tot].to=v,edge[tot].nxt=head[u],head[u]=tot;
}
inline void dfs(int u,int f)
{
fa[root][u]=f;
for(int i=head[u],v;i;i=edge[i].nxt)
{
v=edge[i].to;
if(v!=f)
dfs(v,u);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<n;i++)
{
scanf("%d %d",&x[i],&y[i]);
addedge(x[i],y[i]),addedge(y[i],x[i]);
}
for(int i=1;i<=n;i++)
root=i,dfs(i,0);
scanf("%d",&m);
for(int i=0;i<m;i++)
{
scanf("%d %d %d",&u[i],&v[i],&d[i]);
int a=u[i],b=v[i];
int fb=fa[a][b];
while(fb!=a)
{
ans[fb][b]=ans[b][fb]=max(ans[fb][b],d[i]);
b=fb;
fb=fa[a][fb];
}
ans[fb][b]=ans[b][fb]=max(ans[fb][b],d[i]);
}
bool flag=1;
for(int i=0;i<m&&flag;i++)
{
int a=u[i],b=v[i];
int fb=fa[a][b];
int MIN=INF;
while(fb!=a)
{
MIN=min(ans[fb][b],MIN);
b=fb;
fb=fa[a][fb];
}
MIN=min(ans[fb][b],MIN);
if(MIN!=d[i])
flag=0;
}
if(flag)
{
for(int i=1;i<n;i++)
{
if(!ans[x[i]][y[i]])
ans[x[i]][y[i]]=1;
printf("%d ",ans[x[i]][y[i]]);
}
}
else
printf("-1\n");
return 0;
}