BSOJ 2927 -- 【模拟试题】保镖排队
来源:互联网 发布:魏无羡捏脸数据 编辑:程序博客网 时间:2024/04/19 22:28
Description
【问题背景】
教主LHX作为知名人物,时刻会有恐怖分子威胁他的生命。于是教主雇佣了一些保镖来保障他的人生安全。
【问题描述】
教主一共雇佣了N个保镖,编号为1~N。每个保镖虽然身手敏捷武功高强,但是他在其余N-1个保镖里,都会有一个“上司”,他会对他的上司言听计从。但一号保镖例外,他武功盖世,不惧怕其余任何保镖,所以他没有上司。
教主LHX会对这N个保镖进行定期视察。每次视察的时候,首先会让所有保镖排队。
对于每个保镖,在他心目中会对他的所有下属的武功实力排个队。
现在教主要求排出来的队伍满足:①互为上司-下属的两个保镖,上司在前,下属在后 ②对于一个保镖的所有下属,武功实力较强的在前,较弱的在后。
教主想知道,总的排队方法数除以10007的余数是多少。
Input
输入的第一行为一个正整数T,表示了数据组数。
对于每组数据:
第一行为一个正整数N。
接下来N行,每行描述一个保镖。
第i+1行,会有一个整数K,代表第i个保镖的下属个数,接下来K个数,代表第i个保镖的下属按照武功实力从高到低的编号。
Output
输出包括C行,每行对于每组数据输出方案数mod 10007后的结果。
Sample Input
2
5
2 2 3
2 4 5
0
0
0
7
2 2 3
2 4 5
2 6 7
0
0
0
0
Sample Output
3
10
Hint
【样例解释】
对于第1组数据,有以下3种排列是合法的:
1 2 4 3 5
1 2 3 4 5
1 2 4 5 3
同时满足了1在2与3之前且2在3之前,2在4与5之前且4在5之前
【数据范围】
对于20%的数据,有N ≤ 9;
对于40%的数据,有对于所有K,有K ≤ 2;
对于60%的数据,有N ≤ 100;
对于100%的数据,有T ≤ 10,N ≤ 1000,K ≤ N。
看着是一棵多叉树,可是根据题意描述,按照排列顺序,可以发现恰好是儿子兄弟的二叉树表示法
(其实就是一个先决条件,就是必须把父亲排在前面)
然后转化成二叉树,拓扑方案数?因为这是在二叉树上,所以是可做的(如果是有向无环图,这个问题就是NP问题了,只能通过状压解决小规模数据)。
下面是推导过程:
设
根据乘法原理
其中
若
则
不妨设在l的拓扑序列中插入r的序列。
即在
因为r的序列顺序是固定的,我们只需考虑在每个位置的插入个数。
设在第一个空位插入
则有
即
在两边加上
把
,即
即
可得
/*苍天负我笑,痴情待明朝*/#include<algorithm>#include<cstdio>#include<iostream>#include<cmath>#include<cstring>#include<queue>#include<map>#include<set>#define mp makepairusing namespace std;typedef long long ll;typedef pair<ll,ll> pll;typedef pair<int,int>pii;const int Mod = 10007;int n;int to[1005],nex[1005],h[1005],cnt=0,size[1005];ll F[1005];void exgcd(int a,int b, int &x,int &y){ if(b==0){ x=1;y=0;return ; } else {exgcd(b,a%b,y,x);y-=x*(a/b);return;};}int C(int a,int b){ int x,y,temp=1; for(int i=1;i<=b;i++){ temp=(temp*(a-b+i))%Mod; exgcd(i,Mod,x,y); x=(x%Mod+Mod)%Mod; temp=(temp*x)%Mod; } return temp;}void dfs(int v){ size[v]=1;F[v]=1; for(int i=h[v];i;i=nex[i]){ dfs(to[i]); size[v]+=size[to[i]]; F[v]=(F[v]*F[to[i]])%Mod; if(i!=h[v]){ F[v]=(F[v]*C(size[v]-1,size[to[i]]))%Mod; } }}int main(){ int T; scanf("%d",&T); while(T--){ int x,y;cnt=0; memset(h,0,sizeof(h)); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&x); int f=i; for(int j=1;j<=x;j++){ scanf("%d",&y); cnt++;to[cnt]=y;nex[cnt]=h[f];h[f]=cnt; f=y; } } dfs(1); cout<<F[1]<<"\n"; } return 0;}
- BSOJ 2927 -- 【模拟试题】保镖排队
- 【JZOJ】 【NOIP2014】【模拟试题】保镖排队
- 保镖排队
- Orz教主第6次模拟赛之保镖排队
- BSOJ : 2637 【模拟试题】数独
- bsoj 3733 【模拟试题】打印文章(hdu3507)
- 【动态规划】保镖排队
- 【树形DP】保镖排队
- bsoj:1773 -- 【模拟试题】最远距离点对
- CCF模拟试题之学生排队
- BSOJ 4506: 图形变换 模拟
- 保镖
- [jzoj]1794. 保镖排队(树形DP+想法)
- NOI模拟:保镖(Hall定理)
- 【NOIP practice】BSOJ 3140 冲出亚洲 模拟
- Bsoj 1322 【练习试题】第K小数
- jzoj 5000. 【NOI2017模拟3.4】保镖 hall定理+搜索
- 银行排队模拟
- JavaFX仿QQ2016
- SIM900A访问HTTP的简单方法
- Mysql语句修改查询函数等
- 使用js转化画布与图片(canvas与img)
- Android实战教程
- BSOJ 2927 -- 【模拟试题】保镖排队
- php实现无限极分类
- 设计模式的学习
- Linux下默认安装lamp路径
- 关系型数据库基础(一)
- Springboot 之 多文件上传-知识林
- tjut 5938
- css3第一天(上)
- SharedPreferenceUtil