2017模拟赛 宾馆(数学+搜索)

问题描述

何老板开了一间宾馆,共n个房间,通过n-1双向道路相连,每条道路的长度相同,任意两个房间都有且仅有一条路径可以到达。有三名同行的顾客需要各开一个房间。三个客人要求住的房间要互不相同,且三个房间两两距离相同。

何老板想知道,有多少种方案能让他们满意?

输入格式

第一行一个数n。

接下来n-1行,每行两个数x,y,表示x和y之间有一条道路相连。

输出格式

一个整数,表示满足要求的方案数。

题解

已知若三点两两间距离相等,那么必定存在一点到三点之间距离相同。
考虑到数据范围,暴力枚举每个点,考虑每一个该点的子树的贡献。

代码中的计算方式非常机智
s1表示选一种可能的情况
s2表示选两种可能的情况

代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
#define maxn 10005
#define ll long long
int Next[maxn],Last[maxn],End[maxn];
int num[maxn];
ll sum,s1[maxn],s2[maxn],ans;
int cnt;
int dep[maxn];
int n;
int maxx;
void insert(int x,int y)
{
    Next[++cnt]=Last[x];
    Last[x]=cnt;
    End[cnt]=y;
}
void dfs(int x,int fr,int y)
{
    maxx=max(maxx,y);
    dep[y]++;
    for(int i=Last[x];i;i=Next[i]){
        int en=End[i];
        if(en!=fr){
            dfs(en,x,y+1);
        }
    }
}
int main()
{
    int i,j;
    scanf("%d",&n);
    for(i=1;i<=n-1;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        insert(x,y);
        insert(y,x);
    }
    for(i=1;i<=n;i++){
        memset(s1,0,sizeof(s1));
        memset(s2,0,sizeof(s2));
        maxx=0;
        for(j=Last[i];j;j=Next[j]){
            memset(dep,0,sizeof(dep));
            int en=End[j];
            dfs(en,i,1);
            for(int k=1;k<=maxx;k++){
                ans+=dep[k]*s2[k];
                s2[k]+=s1[k]*dep[k];
                s1[k]+=dep[k];
            }
        }
    }
    cout<<ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值