• 【启发式搜索】Codechef March Cook-Off 2018. Maximum Tree Path


     有点像计蒜之道里的 京东的物流路径 

    题目描述

    给定一棵 N 个节点的树,每个节点有一个正整数权值。记节点 i 的权值为 Ai。
    考虑节点 u 和 v 之间的一条简单路径,记 dist(u, v) 为其长度,gcd(u, v) 为路径上所有节点
    (包含 u 和 v)的权值的最大公因子。min(u, v) 为路径上所有节点的权值的最小值。
    请求出所有节点对 (u, v) 中 dist(u, v) · gcd(u, v) · min(u, v) 的最大值

    输入格式

    输入的第一行包含一个整数 T,代表测试数据的组数。接下来是 T 组数据。
    每组数据的第一行包含一个整数 N,代表树中节点的个数。接下来一行包含 N 个整数
    A1, A2, . . . , AN。
    接下来 N − 1 行,每行包含三个整数 u, v, w,代表节点 u 和 v 之间连有一条长度为 w 的边。

    输出格式

    对于每组数据,输出一行,包含一个整数,代表所求答案

    数据范围

    • 1 ≤ T ≤ 100
    • 2 ≤ N ≤ 10^5
    • 2 ≤ ∑N ≤ 10^5
    • 1 ≤ Ai ≤ 10^4
    • 1 ≤ u, v ≤ N
    • 1 ≤ w ≤ 10^5


    题目分析

    常规做法

    和京东的物流路径不同的是,需要在外层枚举路径的gcd,并把两端点是gcd倍数的边存下,按照端点权值的较小值排序。之后就相当于是用这些边来和那题一样做了。

    参见:[树的直径] Codechef March Cook-Off 2018. Maximum Tree Path

    启发式搜索

    我也不知道复杂度是多少

    每一次搜索时若$dia*mn*gcd(dia为直径)<ans$就return。

     1 #include<bits/stdc++.h>
     2 typedef long long ll;
     3 const int maxn = 100035;
     4 
     5 struct Edge
     6 {
     7     int y,val;
     8     Edge(int a=0, int b=0):y(a),val(b) {}
     9 }edges[maxn<<1];
    10 long long ans;
    11 int tt,n,dia,S,T,a[maxn],dis[maxn];
    12 int edgeTot,head[maxn],nxt[maxn<<1];
    13 
    14 int read()
    15 {
    16     char ch = getchar();
    17     int num = 0;
    18     bool fl = 0;
    19     for (; !isdigit(ch); ch=getchar())
    20         if (ch=='-') fl = 1;
    21     for (; isdigit(ch); ch=getchar())
    22         num = (num<<1)+(num<<3)+ch-48;
    23     if (fl) num = -num;
    24     return num;
    25 }
    26 int gcd(int a, int b){return !b?a:gcd(b, a%b);}
    27 void addedge(int u, int v)
    28 {
    29     int c = read();
    30     edges[++edgeTot] = Edge(v, c), nxt[edgeTot] = head[u], head[u] = edgeTot;
    31     edges[++edgeTot] = Edge(u, c), nxt[edgeTot] = head[v], head[v] = edgeTot;
    32 }
    33 void dfs(int x, int fa, int c)
    34 {
    35     dis[x] = c;
    36     for (int i=head[x]; i!=-1; i=nxt[i])
    37         if (edges[i].y!=fa) dfs(edges[i].y, x, c+edges[i].val);
    38 }
    39 void fnd(int x, int fa, ll d, int g, int mn)
    40 {
    41     if (1ll*dia*g*mn <= ans) return;
    42     if (ans < 1ll*d*g*mn) ans = 1ll*d*g*mn;
    43     for (int i=head[x]; i!=-1; i=nxt[i])
    44         if (edges[i].y!=fa)
    45             fnd(edges[i].y, x, d+1ll*edges[i].val, gcd(g, a[edges[i].y]), std::min(mn, a[edges[i].y]));
    46 }
    47 void fndDiameter()
    48 {
    49     S = T = 0, dis[0] = -0x3f3f3f3f;
    50     dfs(1, 1, 0);
    51     for (int i=1; i<=n; i++)
    52         if (dis[S] < dis[i]) S = i;
    53     dfs(S, S, 0);
    54     for (int i=1; i<=n; i++)
    55         if (dis[T] < dis[i])
    56             T = i, dia = dis[T];
    57     fnd(S, S, 0, a[S], a[S]);
    58 }
    59 int main()
    60 {
    61     tt = read();
    62     while (tt--)
    63     {
    64         n = read(), ans = dia = edgeTot = 0;
    65         memset(head, -1, (n+2)<<2);
    66         for (int i=1; i<=n; i++) a[i] = read();
    67         for (int i=1; i<n; i++) addedge(read(), read());
    68         fndDiameter();
    69         for (int i=1; i<=n; i++)
    70             fnd(i, i, 0, a[i], a[i]);
    71         printf("%lld
    ",ans);
    72     }
    73     return 0;
    74 }

     

    END

  • 相关阅读:
    Kali渗透测试——UPNP网关发现工具Miranda
    Kali渗透测试——UPNP网关发现工具Miranda
    Kali渗透测试——EtherApe
    Kali渗透测试——EtherApe
    ValueError: Input 0 of node import/save/Assign was passed float from import/beta1_power:0 incompatib
    tensorflow C++:You must define TF_LIB_GTL_ALIGNED_CHAR_ARRAY for your compiler
    tensorflow C++手写数字识别
    使用C/C++编写Python扩展库
    软中断和硬中断
    系统调用和函数调用
  • 原文地址:https://www.cnblogs.com/antiquality/p/9915784.html
Copyright © 2020-2023  润新知