2015 多校赛 第七场 1011 (hdu 5379)

题意:给定一棵树,树上有 n 个节点。问有多少种方案,使得在每个节点上依次放置数 1~n 后,每个节点的儿子节点上的数连续(比如 1 为根,有1-2,1-3,1-4,则令2,3,4上的数连续),每个子树上的数连续。

注释在代码里。

#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int maxn=100005;
const int mod=1e9+7;
vector<int>g[maxn];
int n,u,v,t,vis[maxn],flag;
long long ans;
void dfs(int u){
    if(!flag) return;
    int son=g[u].size(),cnt=0;
    vis[u]=1;
    for(int i=0;i<son;i++){
        if(vis[g[u][i]]) continue;
        if(g[g[u][i]].size()==1&&vis[g[u][i]]==0) cnt++;//cnt为当前节点的叶子节点的总数
        else dfs(g[u][i]);
    }
    if(u!=1) son--;//存图方式为无向,因此除1以外都会多一个父亲节点,故减去
    if(son-cnt>2){//如果非叶子节点总数大于2,则无解
        flag=0;return;
    }
    if(cnt!=son)//如果存在非叶子节点
        ans=ans*2%mod;
    while(cnt>0){//叶子节点的阶乘
        ans=ans*cnt%mod;
        cnt--;
    }
}
int main(){
    scanf("%d",&t);
    for(int c=1;c<=t;c++){
        flag=1;
        for(int i=1;i<=n;i++) g[i].clear();
        memset(vis,0,sizeof(vis));
        scanf("%d",&n);
        for(int i=1;i<n;i++){
            scanf("%d%d",&u,&v);
            g[u].push_back(v);
            g[v].push_back(u);
        }
        ans=2;//初始至少有两种方案,即一个根节点与其一个子节点
        if(n!=1) dfs(1);
        else ans=1;//节点数为1则只可能有一种方案
        if(!flag) ans=0;
        printf("Case #%d: %lld\n",c,ans%mod);
    }
    return 0;
}

 

posted @ 2015-08-15 14:51  轶辰  阅读(132)  评论(0编辑  收藏  举报