1. 程式人生 > >2015多校第7場 HDU 5379 Mahjong tree 構造,DFS

2015多校第7場 HDU 5379 Mahjong tree 構造,DFS

print () name long scanf 2015多校 printf color tree

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=5379

題意:一顆n個節點n-1條邊的樹,現在要給每個節點標號(1~n),要求:(1)每一層的兄弟節點的標號要是連續的(2)每一顆子樹的所有節點標號是連續的。問有多少種標號方案。

解法:對於每一層頂多只能存在2個非葉子節點,否則無解;對於每一層有x個葉子節點,y個非葉子節點,那麽ans=(ans * x!)%mod,另外如果y!=0,還得ans=2*ans%mod。

#include <bits/stdc++.h>
using namespace std;
typedef long long
LL; const int maxn = 100010; const int mod = 1e9+7; int head[maxn],edgecnt, ks; bool flag; struct edge{ int to,next; }E[maxn*2]; LL fac[maxn]; LL ans; void init(){ flag = 1; ans = 1; memset(head,-1,sizeof(head)); edgecnt=0; } void INIT(){ fac[0] = 1; for(int i=1; i<maxn; i++){ fac[i]
= fac[i-1]*i%mod; } } void add(int u,int v){ E[edgecnt].to=v,E[edgecnt].next=head[u],head[u]=edgecnt++; } LL dfs(int u, int pre){ if(!flag) return 0; LL s = 1, all = 0, ss = 0; //all代表葉子節點 //ss代表非葉子節點 for(int i = head[u]; ~i; i=E[i].next){ int to = E[i].to; if(to == pre) continue
; LL x = dfs(to, u); s += x; if(x == 1) all++; else if(x>1) ss++; } if(ss>2) flag=false; else{ ans=(ans*fac[all])%mod; if(ss!=0) ans=(ans*2LL)%mod; } return s; } int main() { ks = 0; int T, n; INIT(); scanf("%d", &T); while(T--){ init(); scanf("%d", &n); for(int i=1; i<n; i++){ int u,v; scanf("%d %d", &u,&v); add(u,v); add(v,u); } dfs(1, -1); if(n>1) ans=ans*2; if(!flag) ans=0; printf("Case #%d: %lld\n", ++ks, ans%mod); } return 0; }

2015多校第7場 HDU 5379 Mahjong tree 構造,DFS