q
小明现在有一个\(N\)个点的树, 每条边的长度有一个边权, 现在定义\(dis(i,j)\)代表第\(i\)个点到第\(j\)个点的距离模\(2\)之后的结果。 问有多少\((i,j,k)\)满足\(dis(i,j)=dis(i,k)=dis(j,k)\)
先搞一搞\(dfs\)求出每一个点到达其他点的距离,然后统计从点\(u\)出发到达其他点的路径中长度为\(0\)的有多少,长度为\(1\)的有多少少.
设:
- \(cnt[u][0],cnt[u][1]\)分别为从\(u\)出发的边中长度为\(0,1\)的边数
注意边\((u,u)\)也应该统计在\(cnt[u][0]\)中
对于任意一个点 \(u\), 包含\(u\)在内的构成"边权不同的\((u,v,w)\)"一共有\(cnt[u][0]\times cnt[u][1]\times 6\)个\(\{(u,v,w),(u,w,v),(v,w,u),(v,u,w),(w,u,v),(w,v,u),\}\)
因为所有"边权不完全相同的三角形"必定为两边相同一边不同,所以同一个序列会被计算两次:分别在统计从连接两条不同边权的边的结点的时候
所以可以算出答案为\(n^3-3\sum_{u=1}^n cnt[u][0]\times cnt[u][1]\)
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int MAXN=1e3+5;
int dis[MAXN][MAXN],cnt[MAXN][2];
struct Edge
{
int to,d;
Edge(int t=0,int dist=0):to(t),d(dist){}
};
vector<Edge>e[MAXN];
void dfs(int root,int fa,int u,int d)
{
cnt[root][d] ++;
dis[root][u]=d;
for(int i=0;i<e[u].size();i++)
{
int v=e[u][i].to;
if(v!=fa) dfs(root,u,v,(d+e[u][i].d)%2);
}
}
int main()
{
// freopen("q.in","r",stdin);
// freopen("q.out","w",stdout);
int n;
scanf("%d",&n);
for(int i=1;i<=n-1;i++)
{
int u,v,w;
scanf("%d %d %d",&u,&v,&w);
e[u].push_back(Edge(v,w%2));
e[v].push_back(Edge(u,w%2));
}
for(int u=1;u<=n;u++) dfs(u,0,u,0);
int ans=0;
for(int u=1;u<=n;u++)
ans += cnt[u][0]*cnt[u][1]*3;
ans=n*n*n-ans;
printf("%d",ans);
return 0;
}
其实一开始我是用的\(LCA\)求的任意两点之间的距离,,,结果改统计答案的方法时不知为何错了...好吧先放着吧,等以后再查吧.