zoukankan      html  css  js  c++  java
  • [51nod 1673] 树有几多愁

    题目链接

    显然一定存在最优解满足编号小的节点深度越深,即从小到大的优先选择(叶节点|除自己以外子树节点都已经被标号)的节点标号(影响最小),存在取法(顺序)得到最优解。

    因此考虑对叶节点状压,转移过程中需要计算出当前已经被直接或间接地确定的节点的数量c作为下一个叶节点的编号。复杂度O((n+n)2^20)是不行的

    但考虑到叶子节点不过20个,则虚树(叶子节点是关键点)总结点不过40个,因此利用序树加速就好了。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=1e5+3;
    const int P=1e9+7;
    
    int n,m,cnt;
    int fa[41],val[41],siz[41],id[21];
    vector<int> G[N];
    
    int f[1<<20],t[41];
    double g[1<<20];
    
    void dfs(int x,int p,int d,int w) {
    	if(G[x].size()==2) {
    		for(int y:G[x]) if(y!=p) dfs(y,x,d,w+(d!=0));
    		return;
    	}
    	cnt++; fa[cnt]=d; 
    	siz[cnt]=val[cnt]=w; d=cnt;
    	if(G[x].size()==1) id[m++]=d;
    	for(int y:G[x]) if(y!=p) dfs(y,x,d,1);
    	siz[fa[d]]+=siz[d];
    }
    
    int main() {
    	scanf("%d",&n);
    	for(int x,y,i=n; --i; ) {
    		scanf("%d%d",&x,&y);
    		G[x].push_back(y);
    		G[y].push_back(x);
    	}
    	G[1].push_back(0);
    	dfs(1,0,0,1);
    	memset(f,-0x3f,sizeof f);
    	memset(g,-0x7f,sizeof g);
    	f[0]=1; g[0]=1;
    	for(int s=0; s<(1<<m); ++s) {
    		int now=0;
    		memset(t,0,sizeof t);
    		for(int x=0; x<m; ++x) if(!((s>>x)&1)) t[id[x]]=-1;
    		for(int x=cnt; x; --x) {
    			if(t[x]==siz[x]-val[x]) now+=val[x],t[x]+=val[x];
    			t[fa[x]]+=t[x];
    		}
    		for(int x=0; x<m; ++x) if(!((s>>x)&1)) {
    			if(g[s|(1<<x)]<g[s]*(now+1)) {
    				g[s|(1<<x)]=g[s]*(now+1);
    				f[s|(1<<x)]=1LL*f[s]*(now+1)%P;
    			}
    		}
    	}
    	printf("%d
    ",f[(1<<m)-1]);
    	return 0;
    }
    
  • 相关阅读:
    javacv 通过rtsp 获取视频流 设置帧率
    Firefly-RK3399 上编译安装 OpenCV 3
    萤火虫系统(firefly) RK3399 python3 安装 tensorflow
    Linux环境创建交换分区
    python模块发布
    Docker学习
    好书收集
    python 内存管理和垃圾回收机制
    redis加分布式锁
    邀请关系设计
  • 原文地址:https://www.cnblogs.com/nosta/p/11027309.html
Copyright © 2011-2022 走看看