[XSY 1158] Triangle

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[XSY 1158] Triangle相关的知识,希望对你有一定的参考价值。

题意

  给定一棵 $n$ 个节点的树, 每条边有边权 $w$ .

  $m$ 组询问 $(x, y)$ : 求 $path(x, y)$ 上的所有边权中, 是否能够找出三条, 组成三角形.

  $n \le 100000$ .

 

分析

  不妨设权值的集合为 $\left\{ a_1, a_2, ..., a_k \right\}(a_1 \le a_2 \le ... \le a_k)$ .

  如果存在三条, 那么一定 $\exists i \in [1, k-2], a_i + a_{i+1} > a_{i+2}$ .

  也就是说, 暴力判定的复杂度是 $O(k \log k)$ .

 

  我们尝试找到更多性质, 来更好的求解这个问题.

  假设组成不了三角形, 那么要求 $a_{i+2} \ge a_i + a_{i+1}$ , 而增长最慢的情况是 $a_{i+2} = a_i + a_{i+1}$ .

  但这样已经够快了, 是斐波那契数列.

  所以只要超出 50 项左右, 就一定有解.

 

实现

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <algorithm>
#include <vector>
using namespace std;

#define F(i, a, b) for (register int i = (a); i <= (b); i++)

const int N = 200005;

int n, m;
struct Edge {
    int v, d, nx;
    inline Edge(int _v = 0, int _d = 0, int _nx = 0): v(_v), d(_d), nx(_nx) {}
}mp[N];
int tot, hd[N];

int par[N], dep[N], w[N];
int s[N], top;

inline int rd(void) {
    int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == -) f = -1;
    int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-0; return x*f;
}

inline void Ins(int u, int v, int d) { mp[++tot] = Edge(v, d, hd[u]), hd[u] = tot; }
void Prework(int x) {
    for (int k = hd[x]; k > 0; k = mp[k].nx)
        if (mp[k].v != par[x]) {
            par[mp[k].v] = x, dep[mp[k].v] = dep[x]+1, w[mp[k].v] = mp[k].d;
            Prework(mp[k].v);
        }
}

int main(void) {
    #ifndef ONLINE_JUDGE
        freopen("xsy1158.in", "r", stdin);
        freopen("xsy1158.out", "w", stdout);
    #endif
    
    for (int nT = rd(), t = 1; t <= nT; t++) {
        tot = 0, memset(hd, 0, sizeof hd);
        n = rd();
        F(i, 1, n-1) {
            int u = rd(), v = rd(), d = rd();
            Ins(u, v, d), Ins(v, u, d);
        }
        
        memset(par, 0, sizeof par), memset(dep, 0, sizeof dep), memset(w, 0, sizeof w);
        Prework(1);
        
        printf("Case #%d:\n", t);
        m = rd();
        F(i, 1, m) {
            int u = rd(), v = rd();
            for (top = 0; top <= 50 && u != v; )
                dep[u] > dep[v] ? (s[++top] = w[u], u = par[u]) : (s[++top] = w[v], v = par[v]);
            if (top > 50) puts("Yes");
            else {
                bool done = false;
                sort(s+1, s+top+1);
                for (int j = 1; j+2 <= top && !done; j++)
                    if (s[j] + s[j+1] > s[j+2])
                        done = true, puts("Yes");
                if (!done) puts("No");
            }
        }
    }
    
    return 0;
}

 

以上是关于[XSY 1158] Triangle的主要内容,如果未能解决你的问题,请参考以下文章

XSY3209RGB Sequence

51nod1158 单调栈 个人的想法以及分析

LSTM预测基于matlab贝叶斯网络改进LSTM预测含Matlab源码 1158期

xsy1529小Q与进位制 - 分治FFT

1158: 零起点学算法65——进制转换

XSY3163