【题】【搜索+数学】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
- 【题】【搜索+数学】NKOJ3867 宾馆
- 2017模拟赛 宾馆(数学+搜索)
- 2017-04-04 水题信心 01宾馆房间
- 理想宾馆
- 太阳宾馆
- 宾馆策略
- 【搜索】【RQNOJ】Fish学数学
- hdu 4294 还是搜索+数学
- 如何便宜住宾馆
- 宾馆客房管理程序
- 宾馆客房管理系统
- 宾馆无线路设置
- 铁山宾馆
- java 宾馆管理系统
- 宾馆管理系统
- 免费宾馆软件 JDPMS
- 宾馆的扫描仪维修
- 南阳宾馆管理系统
- 计算运行时间工具timeit
- 矩阵运算——平移,旋转,缩放
- TreeView的图标个性化和动态数据加载
- 【11.8】P73 T1
- 根据股票列表 下载日k数据 存入mongodb
- 【题】【搜索+数学】NKOJ3867 宾馆
- Atitit 图像处理—图像形态学(膨胀与腐蚀)
- 徒手hypervisor(二)
- em, px 以及 rem 之间的区别
- 64. Minimum Path Sum
- two_sum
- css3第三天
- ExpandableListView的用法
- Atitit 图像处理之理解卷积attilax总结