Problem F: tmk找三角
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
No
Yes
No
Yes
果然数据比较中规中矩,并没有太极端的情况。
我的做法也不难想到,一开始深搜给每个结点标上深度。然后根据深度来查找到两个点之前的路径,记录下来。最后统计看一看能不能组成三角形就行了。
#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e5+7;
const int mod=10007;
map<pair<int,int>,int>tu;
struct node
{
int v,w;
node(int x,int y)
{
v=x;
w=y;
}
};
vector<int>head[MAXN];
int n,m,k;
int deep[MAXN];
int pre[MAXN];
void dfs(int u,int fa,int d)
{
deep[u]=d;
for(int i=0,l=head[u].size(); i<l; ++i)
{
int v=head[u][i];
if(v==fa)continue;
pre[v]=u;
dfs(v,u,d+1);
}
}
int ans[MAXN];
bool getPath(int u,int v)
{
int cnt=0;
if(deep[v]>=deep[u])
{
while(deep[v]>deep[u])
{
ans[cnt++]=tu[make_pair(pre[v],v)];
v=pre[v];
}
while(u!=v)
{
ans[cnt++]=tu[make_pair(pre[u],u)];
ans[cnt++]=tu[make_pair(pre[v],v)];
u=pre[u];
v=pre[v];
}
}
else
{
while(deep[u]>deep[v])
{
ans[cnt++]=tu[make_pair(pre[u],u)];
u=pre[u];
}
while(u!=v)
{
ans[cnt++]=tu[make_pair(pre[u],u)];
ans[cnt++]=tu[make_pair(pre[v],v)];
u=pre[u];
v=pre[v];
}
}
if(cnt<3)return 0;
sort(ans,ans+cnt);
for(int i=0;i<cnt-2;++i)
{
if(ans[i]+ans[i+1]>ans[i+2])return 1;
}
return 0;
}
int main()
{
int t;
scanf("%d",&t);
int u,v,w;
while(t--)
{
scanf("%d",&n);
tu.clear();
for(int i=1;i<=n;++i)head[i].clear();
for(int i=0; i<n-1; ++i)
{
scanf("%d%d%d",&u,&v,&w);
head[u].push_back(v);
head[v].push_back(u);
tu[make_pair(u,v)]=w;
tu[make_pair(v,u)]=w;
}
dfs(1,0,0);
scanf("%d",&m);
while(m--)
{
scanf("%d%d",&u,&v);
if(getPath(u,v))puts("Yes");
else puts("No");
}
}
return 0;
}