题目链接
思路
- 因为在树上,那么大概率存在些树上的一些规律技巧。 我们通过作图来看,发现只有三个点ABC在同一条路径上,就不能组成三角形。比如下图的ABD三个点,因为距离AB+BD=AD。不满足形成三角形的条件。只要不在同一条路径上的三个点就能形成三角形,那么我们枚举中转点。 比如下图的B,在它的三个子树里面每一个任选一个点出来就能组成三角形。

- 对于不止三个子树的点,我们任选三个子树,再累加上答案。但是这样暴力枚举会超时。
- 因为是选任意三个子树出来,我们可以这样想,当前枚举的子树A, 已经走过的子树B,还没有走过的子树C。我们每次从这三个区域各个选一个点出来,那么就能做到不重不漏的计数了。

AC代码
#include<bits/stdc++.h>
#define rep(i,x,y) for(int i=x; i<=y; ++i)
#define per(i,x,y) for(int i=x; i>=y; --i)
#define pushk push_back
#define popk pop_back
#define mem(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define ll long long
#define lp p<<1
#define rp p<<1|1
using namespace std;
const int N = 1e6+9;
int sz[N];
ll ans;
vector<int> g[N];
int n;
void dfs(int u,int fa) {
if(g[u].size()==1) {
sz[u]++;
return ;
}
for(auto &it:g[u]) {
if(it==fa) continue;
dfs(it,u);
ans+=1ll*sz[u]*(n-sz[u]-sz[it]-1)*sz[it];
sz[u]+=sz[it];
}
sz[u]++;
}
int main() {
cin>>n;
rep(i,1,n-1) {
int u,v,w;
scanf("%d %d %d",&u,&v,&w);
g[u].pushk(v);
g[v].pushk(u);
}
dfs(1,0);
cout<<ans<<'\n';
return 0;
}
参考
我最先想出来了思路,但是不知道怎么优化枚举,提交上去T了一个点,优化思路是参考这两位大佬。
知乎大佬
csdn大佬
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」