codedorces 1296F Berland Beauty dfs+暴力

32 篇文章 0 订阅

https://vjudge.net/problem/CodeForces-1296F
在这里插入图片描述
在这里插入图片描述
题目大意:给出一棵有 n n n个节点的无根树,对于 m m m个询问 ( u i , v i , d i ) (u_i,v_i,d_i) (ui,vi,di)满足从 u i u_i ui v i v_i vi的路径上的边权的最小值是 d i d_i di,如果可以满足的话输出 n − 1 n-1 n1条边的权值,要求 1 < = f i < = 1 0 6 1<=f_i<=10^6 1<=fi<=106,否则输出 − 1 -1 1

思路:虽然是 F F F题,其实就是一个裸的暴力。依次处理 m m m个询问,找到从 u i u_i ui v i v_i vi的路径,然后把该路径上的边的权值取本身与 d i d_i di的最大值。然后再遍历一遍 m m m个询问,看 u i u_i ui v i v_i vi的路径上的边权的最小值是否等于 d i d_i di,若相等则说明有解,输出每条边的边权即可( 0 0 0可以改成范围内的任意一个值)。树上找任意两点的路径也比较简单,这里提供两种方法:(1)暴力,用二维数组 f a [ u ] [ v ] fa[u][v] fa[u][v]表示以 u u u为根时 v v v的父节点,一共需要 n n n d f s dfs dfs,复杂度 O ( n 2 ) O(n^2) O(n2);(2)用 f a [ v ] fa[v] fa[v]表示以 1 1 1为根时 v v v的父节点,只需 1 1 1 d f s dfs dfs,但是求路径时需要求 L C A LCA LCA,因此复杂度为 O ( n l g n ) O(nlgn) O(nlgn)。以下代码采取第一种方法(懒得写第二种 o r z orz orz)。总复杂度 O ( n ∗ m a x ( n , m ) ) O(n*max(n,m)) O(nmax(n,m))

#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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值