【题】【搜索+数学】NKOJ3867 宾馆

来源:互联网 发布:python变量赋值 引用 编辑:程序博客网 时间:2024/04/27 19:46

NKOJ3867 宾馆
时间限制 : - MS 空间限制 : 165536 KB
评测说明 : 1s

问题描述
何老板开了一间宾馆,共n个房间,通过n-1双向道路相连,每条道路的长度相同,任意两个房间都有且仅有一条路径可以到达。有三名同行的顾客需要各开一个房间。三个客人要求住的房间要互不相同,且三个房间两两距离相同。
何老板想知道,有多少种方案能让他们满意?

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

输出格式
一个整数,表示满足要求的方案数。

样例输入 1
7
1 2
5 7
2 5
2 3
5 6
4 5

样例输出 1
5

样例输入 2
20
1 2
2 3
1 4
3 5
2 6
4 7
6 8
4 9
7 10
10 11
9 12
3 13
9 14
5 15
2 16
6 17
5 18
11 19
4 20

样例输出 2
18

提示
【样例1说明】
{1,3,5},{2,4,6},{2,4,7},{2,6,7},{4,6,7}
【数据范围】
对于30%的数据 1≤N≤100
对于100%的数据 1≤N≤5000

来源 改编自Poi2014 hotel

思路:三个房间两两间路径一定会经过一个中心点,所以依次枚举中心点。
对于某中心点z,再依次枚举各层子孙所能做出的贡献。
枚举子孙时,第一层,为儿子数选3个的组合。以后的每一层,暴力计算贡献数量。
注意:
剪枝1:枚举到某一层时,该子树已没有节点,以后都不枚举该子树了。
剪枝2:若该层有节点的子树小于3,也没有必要加深了

#include<cstdio>#include<iostream>#include<cmath>#include<bitset>#include<vector>using namespace std;const int need=5003;int n;vector<int> w[need];typedef vector<int>::iterator iit;//.................................................inline void in_(int &d){    char t=getchar();    while(t<'0'||t>'9') t=getchar();    for(d=0;!(t<'0'||t>'9');t=getchar()) d=(d<<1)+(d<<3)+t-'0';}//.................................................long long c(const int &n,int m=3){    if(m>n) return 0;    long long c[2]={1,};    for(int i=1;i<=m;i++) c[i&1]=c[(i+1)&1]*(n-i+1)/i;    return c[m&1];}int cnt_son(const int &fa,const int &k,int m){    if(m==1) return w[k].size()-1;    int son=0;    for(iit it=w[k].begin();it!=w[k].end();it++)    {        if(*it!=fa)son+=cnt_son(k,*it,m-1);    }    return son;}long long cnt(const int &k){    bitset<need> bt;     long long ans=c(w[k].size());    if(ans==0) return 0;    int son,tmp;    long long ctmp;    iit it,jt,kt;    for(int i=1;i<=5000;i++)    {        son=tmp=0,ctmp=1;        vector<int> ve;        for(it=w[k].begin();it!=w[k].end();it++)        {            if(bt[*it]) continue;            tmp=cnt_son(k,*it,i);            if(tmp)             {                if(ve.size()==2)                {                    ctmp=ve[0]*ve[1]*tmp;                }                else if(ve.size()>2)                {                    for(jt=ve.begin();jt<ve.end();jt++)                    {                        for(kt=jt+1;kt<ve.end();kt++)                        {                            if(kt==jt) continue;                            ctmp+=tmp*(*jt)*(*kt);                        }                    }                   }                ve.push_back(tmp);            }            else bt[*it]=1;        }        if(ve.size()>=3)ans+=ctmp;        else return ans;    }}//.................................................int main(){    scanf("%d",&n);    for(int i=1,a,b;i<n;i++)    {        in_(a),in_(b);        w[a].push_back(b);        w[b].push_back(a);    }    long long ans=0;    for(int i=1;i<=n;i++) ans+=cnt(i);    cout<<ans;}
0 0
原创粉丝点击