题意

lyk有一棵树,它想给这棵树重标号。

重标号后,这棵树的所有叶子节点的值为它到根的路径上的编号最小的点的编号。

这棵树的烦恼值为所有叶子节点的值的乘积。

lyk想让这棵树的烦恼值最大,你只需输出最大烦恼值对1e9+7取模后的值就可以了。

注意一开始1号节点为根,重标号后这个节点仍然为根。

数据保证叶子节点个数<=20。

思路

由于叶子节点数量很少,所以我们可以考虑状压来决定叶子节点的相对大小,如果已经确定叶子节点的相对大小了,那么就可以用贪心来解决问题了。

对于每一个祖先,它的编号一定大于它的所有儿子。

我们从大到小来枚举所有编号(这里指相对大小)。

令dp[i]表示i这个状态的节点可以得到的最大乘积。

有dp[i]可以转移到dp[i+j],其中j这个状态仅有一个节点,并且那个节点的权值是可以算出来的。

令f[i]表示i这个状态的节点全部向根染色后最终会有多少点被染色。

通过树形DP就能求出权值了。

最大乘积可以通过对数转化为加法来判断,就可以避免高精度了。

代码

# include<bits/stdc++.h>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define eps 1e-8
# define MOD 1000000007
# define INF 1000000000
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(register int i=a; i<=n; ++i)
# define FDR(i,a,n) for(register int i=a; i>=n; --i)
# define bug puts("H");
# define lch p<<1,l,mid
# define rch p<<1|1,mid+1,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
inline char nc(){
static char buf[1000000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int Scan(){
char ch=nc();int sum=0, f=1;
if (ch=='-') f=-1, ch=nc();
while(!(ch>='0'&&ch<='9'))ch=nc();
while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();
return sum*f;
}
const int N=100005;
//Code begin.... struct Node{int head, tail;}node[N];
struct Dp{LL ans; double x;}dp[(1<<20)+5];
int f[1<<20], dep[N], p, nxt[1<<20];
VI g[N]; void dfs(int x, int fa){
dep[x]=dep[fa]+1;
int num=0;
for (auto i=g[x].begin(); i!=g[x].end(); ++i) {
if (*i==fa) continue;
dfs(*i,x); ++num;
if (num==1) node[x].head=node[*i].head, node[x].tail=node[*i].tail;
else {
int now=0;
for (int j=node[x].head; j; j=nxt[j]) for (int k=node[*i].head; k; k=nxt[k]) {
f[j^k]=f[j]+f[k]-dep[x]; nxt[now]=j^k; now=j^k;
}
nxt[node[x].tail]=node[*i].head; nxt[node[*i].tail]=nxt[0]; node[x].tail=now;
}
}
if (num==0) f[1<<p]=dep[x], node[x].head=node[x].tail=1<<p, ++p; }
int main ()
{
int n=Scan(), u, v;
FOR(i,1,n-1) u=Scan(), v=Scan(), g[u].pb(v), g[v].pb(u);
dfs(1,0);
int top=1<<p;
FOR(i,0,top-1) {
dp[i].ans=1;
FOR(j,0,p-1) if ((i>>j)&1) {
if (dp[i].x<dp[i^(1<<j)].x+log(n-f[i]+1)) {
dp[i].x=dp[i^(1<<j)].x+log(n-f[i]+1);
dp[i].ans=dp[i^(1<<j)].ans*(n-f[i]+1)%MOD;
}
}
}
printf("%lld\n",dp[top-1].ans);
return 0;
}

51nod 1673 树有几多愁(链表维护树形DP+状压DP)的更多相关文章

  1. 51nod 1673 树有几多愁——虚树+状压DP

    题目:http://www.51nod.com/Challenge/Problem.html#!#problemId=1673 建一个虚树. 一种贪心的想法是把较小的值填到叶子上,这样一个小值限制到的 ...

  2. 51nod 1673 树有几多愁

    lyk有一棵树,它想给这棵树重标号. 重标号后,这棵树的所有叶子节点的值为它到根的路径上的编号最小的点的编号. 这棵树的烦恼值为所有叶子节点的值的乘积. lyk想让这棵树的烦恼值最大,你只需输出最大烦 ...

  3. 【BZOJ2595_洛谷4294】[WC2008]游览计划(斯坦纳树_状压DP)

    上个月写的题qwq--突然想写篇博客 题目: 洛谷4294 分析: 斯坦纳树模板题. 简单来说,斯坦纳树问题就是给定一张有边权(或点权)的无向图,要求选若干条边使图中一些选定的点连通(可以经过其他点) ...

  4. 刷题总结——树有几多愁(51nod1673 虚树+状压dp+贪心)

    题目: lyk有一棵树,它想给这棵树重标号. 重标号后,这棵树的所有叶子节点的值为它到根的路径上的编号最小的点的编号. 这棵树的烦恼值为所有叶子节点的值的乘积. lyk想让这棵树的烦恼值最大,你只需输 ...

  5. 【62测试】【状压dp】【dfs序】【线段树】

    第一题: 给出一个长度不超过100只包含'B'和'R'的字符串,将其无限重复下去. 比如,BBRB则会形成 BBRBBBRBBBRB 现在给出一个区间[l,r]询问该区间内有多少个字符'B'(区间下标 ...

  6. luogu4294 [WC2008]游览计划(状压DP/斯坦纳树)

    link 题目大意:给定一个网格图,有些点是关键点,选择格点有代价,求把所有关键点联通的最小代价 斯坦纳树模板题 斯坦纳树问题:给定一个图结构,有一些点是关键点,求把这些关键点联通的最小代价e 斯坦纳 ...

  7. [WC2008]游览计划 状压DP,斯坦纳树

    ---题面--- 题解: 这是一道斯坦纳树的题,用状压+spfa来解决 什么是斯坦纳树? 一开始还以为是数据结构来着,其实跟最小生成树很像,大致就是最小生成树只能在各个点之间直接相连,而斯坦纳树则允许 ...

  8. 7月15日考试 题解(链表+状压DP+思维题)

    前言:蒟蒻太弱了,全打的暴力QAQ. --------------------- T1 小Z的求和 题目大意:求$\sum\limits_{i=1}^n \sum\limits_{j=i}^n kth ...

  9. bzoj 4006 [JLOI2015]管道连接(斯坦纳树+状压DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4006 [题意] 给定n点m边的图,连接边(u,v)需要花费w,问满足使k个点中同颜色的 ...

随机推荐

  1. kubernetes 限制网络带宽 annotation -- 注解 -- 类似 label

    1.可以通过给Pod增加 kubernetes.io/ingressbandwidth和 kubernetes.io/egress-bandwidth 这两个annotation来限制Pod的网络带宽 ...

  2. debian jessie 网络设置

    从stable更换到testing后,更新系统apt-get dist-upgrade,然后是等待, 然后不耐烦了不等了,关机! 第二天早上开机apt-get update,找不到源! 用ifconf ...

  3. 大数据入门第十六天——流式计算之storm详解(三)集群相关进阶

    一.集群提交任务流程分析 1.集群提交操作 参考:https://www.jianshu.com/p/6783f1ec2da0 2.任务分配与启动流程 参考:https://www.cnblogs.c ...

  4. 腾讯云CVM服务器怎么建网站

    腾讯云云服务器CVM站在用户的角度看就相当于一台计算机,虽然实际上它是一个虚拟服务器,是一个大的云端服务器集群虚拟出来的一个虚拟服务器,在使用上直接当做一个实际的服务器即可.那么,对于一个新手菜鸟来说 ...

  5. mysql提示Fatal error: Can't open and lock privilege tables: Table 'mysql.host' doesn't exist解决方法

    一次重启mysql发现无法启动成功,通过检查mysql日志发现问题并解决了问题. mysql启动失败的日志: [root@nn ~]# tail -n 20 /var/log/mysqld.log 1 ...

  6. Dynamics CRM Online Administrator password reset

    道道还挺多,好好看看 Dynamics CRM Online Administrator password reset

  7. 【第十三课】监控Linux系统状态

    目录 1.查看系统负载命令:w.uptime 2.vmstat详解 3.top动态查看负载 4.sar命令(监控网卡流量) 5.nload命令(监控网卡流量) 6.iostat iotop(监控IO性 ...

  8. [CF1062F]Upgrading Cities[拓扑排序]

    题意 一张 \(n\) 点 \(m\) 边的 \(DAG\) ,问有多少个点满足最多存在一个点不能够到它或者它不能到. \(n,m\leq 3\times 10^5\) 分析 考虑拓扑排序,如果 \( ...

  9. Java 多线程(五)之 synchronized 的使用

    目录 1 线程安全 2 互斥锁 3 内置锁 synchronized 3.1 普通同步方法,锁是当前实例对象(this) 3.1.1 验证普通方法中的锁的对象是同一个. 3.1.2 验证不同的对象普通 ...

  10. JavaScript快速入门-ECMAScript本地对象(String)

    一.String对象 String对象和python中的字符串一样,也有很多方法,这些方法大概分为以下种类: 1.索引和查找 1.charAt()   返回指定位置的字符. 2.charCodeAt( ...