思路:一眼非常神,其实想一下,要满足三角形必须要a+b>c,那么最坏情况下就是a+b=c再多一点点,那么这不就是一个斐波那契吗?而50项的斐波那契数列就已经大于2^31-1了,那么所以当树上的点大于50个的时候是一定能组成的,少于50个的时候直接抠出来暴力即可
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+7;
vector<pair<int,int> >e[maxn];
int n,dis[maxn],fa[maxn],dep[maxn];
void dfs(int u,int f,int d)
{
dep[u]=d;
for(int i = 0;i<e[u].size();i++)
{
int v = e[u][i].first;
int w = e[u][i].second;
if(v==f)continue;
dis[v]=w;
fa[v]=u;
dfs(v,u,d+1);
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i = 0;i<=n;i++)
{
e[i].clear();
dis[i]=0;
fa[i]=-1;
dep[i]=0;
}
for(int i = 1;i<=n-1;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
e[u].push_back(make_pair(v,w));
e[v].push_back(make_pair(u,w));
}
dfs(1,-1,1);
int q;
scanf("%d",&q);
while(q--)
{
int u,v;
scanf("%d%d",&u,&v);
vector<int>vv;
while(vv.size()<50 && u!=v)
{
if(dep[u]>dep[v])
{
vv.push_back(dis[u]);
u = fa[u];
}
else
{
vv.push_back(dis[v]);
v=fa[v];
}
}
if(vv.size()>50)
{
printf("Yes\n");
continue;
}
else
{
int flag = 0;
sort(vv.begin(),vv.end());
if(vv.size()<3)
{
printf("No\n");
continue;
}
for(int i = 0;i<vv.size()-2;i++)
if(vv[i]+vv[i+1]>vv[i+2])
{
printf("Yes\n");
flag=1;
break;
}
if(!flag)
printf("No\n");
}
}
}
}
Description
有一棵树,树上有只tmk。他在这棵树上生活了很久,对他的构造了如指掌。所以他在树上从来都是走最短路,不会绕路。他还还特别喜欢三角形,所以当他在树上爬来爬去的时候总会在想,如果把刚才爬过的那几根树枝/树干锯下来,能不能从中选三根出来拼成一个三角形呢?
Input
第一行输入一个T,表示有多少组样例。
对于每组数据:第一行包含一个整数 N,表示树上节点的个数(从 1 到 N 标号)。
接下来的 N-1 行包含三个整数 a, b, len,表示有一根长度为 len 的树枝/树干在节点 a 和节点 b 之间。
接下来一行包含一个整数 M,表示询问数。
接下来M行每行两个整数 S, T,表示毛毛虫从 S 爬行到了 T,询问这段路程中的树枝/树干是否能拼成三角形。
Output
对于每组数据,每个询问输出一行,包含"Yes"或“No”,表示是否可以拼成三角形。
Sample Input
251 2 51 3 202 4 304 5 1523 43 551 4 322 3 1003 5 454 5 6021 41 3
Sample Output
NoYesNoYes
HINT
对于20%数据 1 ≤ N, M ≤ 1000
对于所有数据 1 ≤ N ≤ 100000, 1 ≤ M ≤ 100000, 1 ≤ len ≤ 1000000000