您的位置:首页 > 其它

Hdu 5379 Mahjong tree (dfs + 组合数)

2015-08-12 12:32 471 查看
题目链接:

  Hdu 5379 Mahjong tree

题目描述:

  给出一个有n个节点的树,以节点1为根节点。问在满足兄弟节点连续 以及 子树包含节点连续 的条件下,有多少种编号方案给树上的n个点编号?

解题思路:

  对于一个节点来讲,非叶子儿子节点最多有两个才能满足要求,否则满足子树节点连续的话就无法满足兄弟节点连续。然后有dfs计算每棵子树的贡献值,每棵子树的子节点可以分为叶子节点X和非叶子节点Y,叶子节点可以分配到一组连续的编号,非叶子节点只能分配到兄弟节点中最大或者最小编号两种情况,叶子节点的贡献值为X!。然后dfs跑一下就ok咯。

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#pragma comment (linker, "/STACK:1024000000,1024000000")
using namespace std;

const int maxn = 100005;
const int mod = (1e9 + 7);
typedef long long LL;
struct node
{
int to, next;
}edge[maxn*2];
int head[2][maxn], vis[maxn], tot, flag;
LL res;

void Add (int from, int to)
{
edge[tot].to = to;
edge[tot].next = head[0][from];
head[0][from] = tot ++;
head[1][from] ++;
}

void dfs (int u)
{
int k, cnt;
k = cnt = 0;
vis[u] = 1;
for (int i=head[0][u]; i!=-1; i=edge[i].next)
{

int v = edge[i].to;
if (vis[v])
continue;
if (!vis[v] && head[1][v]==1)
cnt ++;
else
dfs (v);
k ++;
}
if (k - cnt > 2)
{
res = 0;
return;
}
if (k != cnt)
res = (res * 2) % mod;
while (cnt)
{
res = (res * cnt) % mod;
cnt --;
}
}
int main ()
{
int t, n, l = 0;
scanf ("%d", &t);

while (t --)
{
scanf ("%d", &n);
memset (head[0], -1, sizeof(head[0]));
memset (head[1], 0, sizeof(head[1]));
memset (vis, 0, sizeof(vis));
tot = flag = 0;

for (int i=1; i<n; i++)
{
int u, v;
scanf ("%d %d", &u, &v);
Add (u, v);
Add (v, u);
}
res = 2;
dfs (1);
printf ("Case #%d: %lld\n", ++l, n==1?1:res);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: