51nod1673樹有幾多愁
阿新 • • 發佈:2019-01-27
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> typedef long long ll; using namespace std; const int mod=1e9+7; const int N=100010; int pre[N*2],last[N],other[N*2],num; bool gg[N],leaf[N]; int len[N],leaf_pos[210],cnt,leafnum,size[N],got[210]; vector<int >vec[210]; double f[(1<<20)+N]; int g[(1<<20)+N]; inline void add(int x,int y){ num++; pre[num]=last[x]; last[x]=num; other[num]=y; } void dfs(int x,int fa){ int son=0; for(int i=last[x];i;i=pre[i]){ int v=other[i]; if(v!=fa){ dfs(v,x); son++; } } leaf[x]=(son==0); if(son==1) gg[x]=1; } void dfs1(int x,int fa,int _fa,int tmplen){ tmplen++; if(!gg[x]){ len[++cnt]=tmplen;tmplen=0;//記錄它上面有幾個點被刪了 if(leaf[x]) leaf_pos[++leafnum]=cnt;//記錄葉子的個數和每個葉子的新的編號 if(_fa) vec[_fa].push_back(cnt);//建新圖 _fa=cnt; } int v; for(int i=last[x];i;i=pre[i]) if((v=other[i])!=fa) dfs1(v,x,_fa,tmplen); } int main(){ int n,x,y; scanf("%d",&n); for(int i=1;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x); dfs(1,0);dfs1(1,0,0,0); int st=(1<<leafnum); for(int i=1;i<=leafnum;i++) size[leaf_pos[i]]++; int sz; for(int i=cnt;i>=1;i--){//按dfs序更新,保證先孩子再父親 for(int j=0,sz=vec[i].size();j<sz;j++) size[i]+=size[vec[i][j]]; } f[0]=g[0]=1; for(int i=0;i<st;i++){ memset(got,0,sizeof(got)); for(int j=0;j<leafnum;j++){ if(i&(1<<j)) got[leaf_pos[j+1]]++; } int now=1; for(int j=cnt;j>=1;j--){ for(int k=0,sz=vec[j].size();k<sz;k++) got[j]+=got[vec[j][k]]; if(got[j]==size[j]) now+=len[j]; } double tmp=f[i]*(double)now; for(int j=0;j<leafnum;j++){ if(((1<<j)&i)==0&&tmp>f[i|(1<<j)]) f[i|(1<<j)]=tmp,g[i|(1<<j)]=1ll*g[i]*now%mod; } } printf("%d\n",g[st-1]); return 0; }