[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的主要内容,如果未能解决你的问题,请参考以下文章