[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;
}
时间: 2024-10-12 04:13:43

[XSY 1158] Triangle的相关文章

(leetcode题解)Pascal&#39;s Triangle

Pascal's Triangle  Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5,Return [ [1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1] ] 题意实现一个杨辉三角. 这道题只要注意了边界条件应该很好实现出来,C++实现如下 vector<vector<int>> generate(int

Lab 1: Write a java program for the triangle problem and test the program with Junit.

Tasks: 1. Install Junit(4.12), Hamcrest(1.3) with Eclipse 将两个jar包添加到工程中 2. Install Eclemma with Eclipse 3. Write a java program for the triangle problem and test the program with Junit. [Description of triangle problem]Function triangle takes three i

Solution to Triangle by Codility

question: https://codility.com/programmers/lessons/4 we need two parts to prove our solution. on one hand, there is no false triangular. Given the array has been sorted, if A[i]+A[i+1]>A[i+2], we can prove the existence of the triangle. for array A i

LeetCode (13) Pascal&#39;s Triangle (杨辉三角 )

题目描述 Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5, Return 从第三行开始,每行除了最左边和最右边两个数为1,其他数字都是上一行中相邻两个数字之和.根据上述规则可以写出下面的代码: class Solution { public: vector<vector<int> > generateRow1() { vector<in

UVA - 11437 - Triangle Fun (计算几何~)

UVA - 11437 Triangle Fun Time Limit: 1000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu Submit Status Description Problem A Triangle Fun Input: Standard Input Output: Standard Output In the picture below you can see a triangle ABC. Point D, E

POJ 1163 The Triangle

题目链接:http://poj.org/problem?id=1163 The Triangle Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 39022   Accepted: 23430 Description 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 (Figure 1) Figure 1 shows a number triangle. Write a program that calculat

LeetCode--Pascal&#39;s Triangle

Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5, Return [ [1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1] ] class Solution { public: vector<vector<int> > generate(int numRows) { vector<vector<in

? (triangle)

2.1 题目描述 给定一个无自环重边的无向图,求这个图的三元环1的个数以及补图2的三元环个数. 2.2 输入格式 第一行 2 个数 n, m ,分别表示图的点数.边数. 接下来 m 行,每行两个数 u, v ,表示一条连接 u, v 的无向边. 2.3 输出格式 一行两个数,依次表示原图的三元环个数以及补图的三元环的个数. 2.4 样例输入 5 5 1 2 1 3 2 3 2 4 3 4 2.5样例输出 2 1 2.6数据范围 对于 30% 的数据:n ≤ 100 对于 60% 的数据:m ≤

POJ 2079 Triangle [旋转卡壳]

Triangle Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 9525   Accepted: 2845 Description Given n distinct points on a plane, your task is to find the triangle that have the maximum area, whose vertices are from the given points. Input