题意:给定一棵树,树上有 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; }
时间: 2024-10-27 04:50:37