题目:
Mahjong tree
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1471 Accepted Submission(s): 448
Problem Description
Little sun is an artist. Today he is playing mahjong alone. He suddenly feels that the tree in the yard doesn‘t look good. So he wants to decorate the tree.(The tree has n vertexs, indexed from 1 to n.)
Thought for a long time, finally he decides to use the mahjong to decorate the tree.
His mahjong is strange because all of the mahjong tiles had a distinct index.(Little sun has only n mahjong tiles, and the mahjong tiles indexed from 1 to n.)
He put the mahjong tiles on the vertexs of the tree.
As is known to all, little sun is an artist. So he want to decorate the tree as beautiful as possible.
His decoration rules are as follows:
(1)Place exact one mahjong tile on each vertex.
(2)The mahjong tiles‘ index must be continues which are placed on the son vertexs of a vertex.
(3)The mahjong tiles‘ index must be continues which are placed on the vertexs of any subtrees.
Now he want to know that he can obtain how many different beautiful mahjong tree using these rules, because of the answer can be very large, you need output the answer modulo 1e9 + 7.
Input
The first line of the input is a single integer T, indicates the number of test cases.
For each test case, the first line contains an integers n. (1 <= n <= 100000)
And the next n - 1 lines, each line contains two integers ui and vi, which describes an edge of the tree, and vertex 1 is the root of the tree.
Output
For each test case, output one line. The output format is "Case #x: ans"(without quotes), x is the case number, starting from 1.
Sample Input
2 9 2 1 3 1 4 3 5 3 6 2 7 4 8 7 9 3 8 2 1 3 1 4 3 5 1 6 4 7 5 8 4
Sample Output
Case #1: 32 Case #2: 16
Author
UESTC
Source
2015 Multi-University Training Contest 7
Recommend
wange2014
题意:给一固定形态的树,有n个节点,现在要给这n个节点赋值,每个节点取1到n的某个数,不能重复,并且满足:1.任意节点的所有子节点的值必须连续 2.任意节点的子树的值必须连续。 问有多少种赋值方法。
思路:由于这两条规则的限制,不能有超过两个非叶子节点,并且非叶子节点一定是取连续区间的端点。这样的话非叶子节点有两种取法,剩下的叶子节点有k!种取法,因为顺序是任意的。所以对于某个根节点而言,它如果有孩子,那么首先他有两种取法,可以取区间最大或最小值,然后孩子中的叶子节点有k!取法,非叶节点再dfs下去求。
代码:
#include <cstdlib> #include <cctype> #include <cstring> #include <cstdio> #include <cmath> #include<climits> #include <algorithm> #include <vector> #include <string> #include <iostream> #include <sstream> #include <map> #include <set> #include <queue> #include <stack> #include <fstream> #include <numeric> #include <iomanip> #include <bitset> #include <list> #include <stdexcept> #include <functional> #include <utility> #include <ctime> using namespace std; #define PB push_back #define MP make_pair #define REP(i,x,n) for(int i=x;i<(n);++i) #define FOR(i,l,h) for(int i=(l);i<=(h);++i) #define FORD(i,h,l) for(int i=(h);i>=(l);--i) #define SZ(X) ((int)(X).size()) #define ALL(X) (X).begin(), (X).end() #define RI(X) scanf("%d", &(X)) #define RII(X, Y) scanf("%d%d", &(X), &(Y)) #define RIII(X, Y, Z) scanf("%d%d%d", &(X), &(Y), &(Z)) #define DRI(X) int (X); scanf("%d", &X) #define DRII(X, Y) int X, Y; scanf("%d%d", &X, &Y) #define DRIII(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z) #define OI(X) printf("%d",X); #define RS(X) scanf("%s", (X)) #define MS0(X) memset((X), 0, sizeof((X))) #define MS1(X) memset((X), -1, sizeof((X))) #define LEN(X) strlen(X) #define F first #define S second #define Swap(a, b) (a ^= b, b ^= a, a ^= b) #define Dpoint strcut node{int x,y} #define cmpd int cmp(const int &a,const int &b){return a>b;} /*#ifdef HOME freopen("in.txt","r",stdin); #endif*/ const int MOD = 1e9+7; typedef vector<int> VI; typedef vector<string> VS; typedef vector<double> VD; typedef long long LL; typedef pair<int,int> PII; //#define HOME int Scan() { int res = 0, ch, flag = 0; if((ch = getchar()) == '-') //判断正负 flag = 1; else if(ch >= '0' && ch <= '9') //得到完整的数 res = ch - '0'; while((ch = getchar()) >= '0' && ch <= '9' ) res = res * 10 + ch - '0'; return flag ? -res : res; } /*----------------PLEASE-----DO-----NOT-----HACK-----ME--------------------*/ #define MAXN 100000 const int mod=1e9+7; vector<int>g[MAXN+5]; int sz[MAXN+5]; int fact[MAXN+5]; int dfs(int u,int f) { int ans=1; sz[u]=1; int son1=0; int son2=0; for(int i=0;i<g[u].size();i++) { int v=g[u][i]; if(v==f) continue; ans=((long long)ans*dfs(v,u))%mod; if(sz[v]>1) son2++; else son1++; sz[u]+=sz[v]; } if(son2>2) return 0; if(son2!=0) ans=((long long)ans*2)%mod; ans=((long long )ans*fact[son1])%mod; return ans; } int main() {int T; RI(T); fact[0]=1; for(int i=1;i<=MAXN;i++) fact[i]=((long long )fact[i-1]*i)%mod; for(int t=1;t<=T;t++) { int n; RI(n); for(int i=0;i<=n;i++) g[i].clear(); for(int i=0;i<n-1;i++) { int u,v; RII(u,v); g[u].push_back(v); g[v].push_back(u); } MS0(sz); int ans=dfs(1,0); if(sz[1]>1) ans=((long long )ans*2)%mod; printf("Case #%d: %d\n",t,ans); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。