q

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\)求的任意两点之间的距离,,,结果改统计答案的方法时不知为何错了...好吧先放着吧,等以后再查吧.

posted @ 2018-10-06 23:59  昤昽  阅读(180)  评论(0编辑  收藏  举报