题目链接:https://ac.nowcoder.com/acm/contest/6760/A
题意:树上找出满足dis(i,j)=dis(j,k)=dis(i,k)的三元组的个数。且dis(i,j)的定义是i到j的距离对2取模
题解:我们可以将两个点之间的距离,全部转换成到根的距离。我的做法就是再找一个节点为0,使它向1连一条长度为0的点,并以0为根(以1为根其实一样),然后我们讲dis(i,j)看成(dis(0,i)+dis(0,j))%2因为是对2取模,所以lca(i,j)到0的路径长会计算两次,取模后没有影响,那么我们稍微推导一下发现,i,j,k三元组若满足题目条件,则i,j,k到根的距离奇偶性相同。这里就考虑全为偶,假设偶数个节点数为x,那么对于i有x种可能,j有x种可能,k也有x种可能,故ans=xxx+yyy;
#include <bits/stdc++.h> using namespace std; typedef long long ll; int n,x,y,z; const int maxn=10005; struct node{int v,w,nxt;}g[maxn<<1]; int head[maxn],tot; void add_edge(int u,int v,int w){g[++tot]={v,w,head[u]};head[u]=tot;} int d[maxn]; int o,j; void build(int u,int fa,int now){ d[u]=now; if (u!=0){ if (d[u]&1)j++; else o++; } for (int i=head[u];i;i=g[i].nxt){ int v=g[i].v; if (v!=fa){ build(v,u,(now+g[i].w)%2); } } } int main(){ cin>>n; for (int i=1;i<n;i++){ scanf("%d%d%d",&x,&y,&z); add_edge(x,y,z); add_edge(y,x,z); } add_edge(0,1,0); build(0,-1,0); ll ans=0; ans=1ll*j*j*j+1ll*o*o*o; cout<<ans<<endl; return 0; }