【Bzoj3522】Hotel

題意

有一個樹形結構,每條邊的長度相同,任意兩個節點可以相互到達。選3個點。兩兩距離相等。有多少種方案?


解析

滿足條件的點對一定是“有一箇中心點,三個點到中心點的距離相等,且三個點分別在不同子樹中”這種情況。(因爲如果在同一子樹中會被重複統計)。
那麼枚舉中心點,然後遍歷子樹,統計答案。
令cnt[i]表示當前子樹中深度爲i的點有多少個。
f[i]表示當前點已經遍歷過的子樹中,深度爲i的點有多少個。
g[i]表示當前點已經遍歷過的子樹中,兩個點深度都爲i的點對有多少個。
根據乘法原理ans += ∑(g[i] * cnt[i])。每次用f和cnt去更新g,用cnt去更新f。



#include <cstdio>
#include <cstring>
#include <algorithm>

#define Rep( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i<=(i##_END);i++)
#define For( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i!=(i##_END);i++)
#define Lop( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i>=(i##_END);i--)
#define Dnt( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i!=(i##_END);i--)

using std :: max;
using std :: min;

typedef long long LL;

const int maxx = 100000 + 25;

int n,m,x,y,z,num;
LL  ans;

int f[maxx],g[maxx],cnt[maxx],son[maxx];
int head[maxx],nxt[maxx],to[maxx];

void Ins(int x,int y){
    to[++num] = y;nxt[num] = head[x];head[x] = num;son[x] ++;
}

void Dfs(int x,int pre,int dpt){
    cnt[dpt] ++;
    for(int i=head[x];i;i=nxt[i])
        if(to[i] != pre)
            Dfs(to[i],x,dpt+1);
}

int main(){
    scanf("%d",&n);
    For( i , 1 , n ) scanf("%d%d",&x,&y),Ins(x,y),Ins(y,x);
    Rep( x , 1 , n ){
        if(son[x] < 3) continue;
        memset(f,0,sizeof(f));
        memset(g,0,sizeof(g));
        for(int i=head[x];i;i=nxt[i]){
            memset(cnt,0,sizeof(cnt));
            Dfs(to[i],x,1);
            Rep( k , 1 , n ){
                ans += (LL)cnt[k] * g[k];
                g[k] += f[k] * cnt[k];
                f[k] += cnt[k];
            }
        }
    }
    printf("%lld\n",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章