题目大意

  给你一棵\(n\)个点的树和\(m\)条路径要求你找出最多的路径,使得这些路径不共边。特别的,每个点的度数\(\leq 10\)。

  \(n\leq 1000,m\leq \frac{n(n-1)}{2}\)

题解

  先对于每个点把相邻的边编号。

  考虑状压DP。

  设\(f_{i,j}\)为以\(i\)个点的子树内,状态为\(j\)的边的子树内的边也没有选(这些边也没选),所选的最多路径数。

  然后对于每个点有很多种选法,分为两类:1.某条边不选,选对应的子树;2.选\(1\)~\(2\)条边和对应的路径,那么这些路径经过的边都不能选。

  然后直接状压DP。

  对于每个点来说,总共有最多\(O(d^2)\)种转移。考虑每个儿子的贡献,就是\(O(d)\)。

  时间复杂度:\(O(n^2+nd2^d)\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
struct list
{
int t[1000010];
pii v[1000010];
int h[1010];
int n;
void clear()
{
memset(h,0,sizeof h);
n=0;
}
void add(int x,pii y)
{
n++;
v[n]=y;
t[n]=h[x];
h[x]=n;
}
};
list l;
int f[1010][1<<10];
int g[1010];
int c[1010][20];
int d[1010];
int ns[12][12];
int e[1010];
void dfs2(int x,int fa,int t,int s)
{
int fc;
int i;
for(i=1;i<=d[x];i++)
if(c[x][i]==fa)
fc=i;
g[x]=s+f[x][((1<<d[x])-1)^(1<<(fc-1))];
e[x]=t;
for(i=1;i<=d[x];i++)
if(c[x][i]!=fa)
dfs2(c[x][i],x,t,s+f[x][((1<<d[x])-1)^(1<<(fc-1))^(1<<(i-1))]);
}
int dd[1010];
int ff[1010];
int lca[1010][1010];
void dfs(int x,int fa,int dep)
{
ff[x]=fa;
dd[x]=dep;
int i;
for(i=1;i<=d[x];i++)
if(c[x][i]!=fa)
dfs(c[x][i],x,dep+1);
}
int getlca(int x,int y)
{
if(x==y)
return x;
if(lca[x][y])
return lca[x][y];
if(dd[x]>dd[y])
return lca[x][y]=getlca(ff[x],y);
return lca[x][y]=getlca(x,ff[y]);
}
void dp(int x,int fa)
{
int i;
for(i=1;i<=d[x];i++)
if(c[x][i]!=fa)
dp(c[x][i],x);
for(i=1;i<=d[x];i++)
if(c[x][i]!=fa)
dfs2(c[x][i],x,i,0);
memset(ns,0,sizeof ns);
int cx,cy,cs;
for(i=l.h[x];i;i=l.t[i])
{
if(l.v[i].first==x)
{
cx=0;
cy=e[l.v[i].second];
cs=g[l.v[i].second];
}
else if(l.v[i].second==x)
{
cx=e[l.v[i].first];
cy=0;
cs=g[l.v[i].first];
}
else
{
cx=e[l.v[i].first];
cy=e[l.v[i].second];
cs=g[l.v[i].first]+g[l.v[i].second];
}
cs++;
if(cx>cy)
swap(cx,cy);
ns[cx][cy]=max(ns[cx][cy],cs);
}
for(i=1;i<=d[x];i++)
if(c[x][i]!=fa)
{
cx=0;
cy=i;
cs=f[c[x][i]][(1<<d[c[x][i]])-1];
ns[cx][cy]=max(ns[cx][cy],cs);
}
int j,k;
for(i=0;i<=d[x];i++)
for(j=0;j<=d[x];j++)
if(ns[i][j])
{
int s=0;
if(i)
s|=1<<(i-1);
if(j)
s|=1<<(j-1);
for(k=0;k<(1<<d[x]);k++)
if(!(k&s))
f[x][k|s]=max(f[x][k|s],f[x][k]+ns[i][j]);
}
}
void solve()
{
memset(d,0,sizeof d);
int n;
scanf("%d",&n);
int i,j;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
lca[i][j]=0;
for(i=1;i<=n;i++)
for(j=0;j<(1<<10);j++)
f[i][j]=0;
l.clear();
int x,y;
for(i=1;i<=n-1;i++)
{
scanf("%d%d",&x,&y);
c[x][++d[x]]=y;
c[y][++d[y]]=x;
}
dfs(1,0,1);
int m;
scanf("%d",&m);
for(i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
l.add(getlca(x,y),pii(x,y));
}
dp(1,0);
int ans=0;
for(i=1;i<=n;i++)
ans=max(ans,f[i][(1<<d[i])-1]);
printf("%d\n",ans);
}
int main()
{
#ifdef DEBUG
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
int t;
scanf("%d",&t);
while(t--)
solve();
return 0;
}

【BZOJ4042】【CERC2014】parades 状压DP的更多相关文章

  1. BZOJ 4042 Luogu P4757 [CERC2014]Parades (树形DP、状压DP)

    题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=4042 (Luogu) https://www.luogu.org/prob ...

  2. BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]

    1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3336  Solved: 1936[Submit][ ...

  3. nefu1109 游戏争霸赛(状压dp)

    题目链接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1109 //我们校赛的一个题,状压dp,还在的人用1表示,被淘汰 ...

  4. poj3311 TSP经典状压dp(Traveling Saleman Problem)

    题目链接:http://poj.org/problem?id=3311 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...

  5. [NOIP2016]愤怒的小鸟 D2 T3 状压DP

    [NOIP2016]愤怒的小鸟 D2 T3 Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可 ...

  6. 【BZOJ2073】[POI2004]PRZ 状压DP

    [BZOJ2073][POI2004]PRZ Description 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍 ...

  7. bzoj3380: [Usaco2004 Open]Cave Cows 1 洞穴里的牛之一(spfa+状压DP)

    数据最多14个有宝藏的地方,所以可以想到用状压dp 可以先预处理出每个i到j的路径中最小权值的最大值dis[i][j] 本来想用Floyd写,无奈太弱调不出来..后来改用spfa 然后进行dp,这基本 ...

  8. HDU 1074 Doing Homework (状压dp)

    题意:给你N(<=15)个作业,每个作业有最晚提交时间与需要做的时间,每次只能做一个作业,每个作业超出最晚提交时间一天扣一分 求出扣的最小分数,并输出做作业的顺序.如果有多个最小分数一样的话,则 ...

  9. 【BZOJ1688】[Usaco2005 Open]Disease Manangement 疾病管理 状压DP

    [BZOJ1688][Usaco2005 Open]Disease Manangement 疾病管理 Description Alas! A set of D (1 <= D <= 15) ...

随机推荐

  1. es6在网页中模块引入的方法

    前言: 以前,当然包括现在的大部分js引入,我们都是利用<script></script>这种全局的方式进行引入,当然这种弊端还是用的,比如这样直接利用script引入的话,会 ...

  2. matplotlib中subplot的使用

    #plt.subplot的使用 import numpy as npimport matplotlib.pyplot as pltx=[1,2,3,4]y=[5,4,3,2]plt.subplot(2 ...

  3. 反射reflect

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制. ...

  4. os.path 下的各方法

    一.os.path os.path.abspath(file) #拿到当前程序(文件)的绝对目录. os.path.split(pathname) # 返回一个元组,第零个元素为文件上级绝对目录,第一 ...

  5. ImageProcessor组件

    ImageProcessor组件 开源免费的.NET图像即时处理的组件ImageProcessor   承接以前的组件系列,这个组件系列旨在介绍.NET相关的组件,让大家可以在项目中有一个更好的选择, ...

  6. rem移动端适配方案

    一. rem vs em 单位 定义 特点 rem font size of the root element 以根元素字体大小为基准 em font size of the element 以父元素 ...

  7. javascript博客爱心特效代码与代码解析

    这个鼠标点击出现爱心的特效经常在别的博客里见到,于是我查了度娘后拿来直接用上了. 虽然不知道原作者是谁,但肯定是个大神,只有通过观摩他/她的代码膜拜一下啦. 直接上代码(解析在代码注释里): // 自 ...

  8. Azure系列2.1.11 —— CloudBlobContainer

    (小弟自学Azure,文中有不正确之处,请路过各位大神指正.) 网上azure的资料较少,尤其是API,全是英文的,中文资料更是少之又少.这次由于公司项目需要使用Azure,所以对Azure的一些学习 ...

  9. Spring 配置详解

    spring4配置文件详解 一.配置数据源 基本的加载properties配置文件 <context:property-placeholder location="classpath* ...

  10. python[练习题]:实现Base64编码

    要求自己实现算法,不用库. Base64简介: Base64是一种用64个字符来表示任意二进制数据的方法. 用记事本打开exe.jpg.pdf这些文件时,我们都会看到一大堆乱码,因为二进制文件包含很多 ...