CF613D:Kingdom and its Cities(树形DP,虚树)
Description
一个王国有n座城市,城市之间由n-1条道路相连,形成一个树结构,国王决定将一些城市设为重要城市。
这个国家有的时候会遭受外敌入侵,重要城市由于加强了防护,一定不会被占领。而非重要城市一旦被占领,这座城市就不能通行。
国王定了若干选择重要城市的计划,他想知道,对于每个计划,外敌至少要占领多少个非重要城市,才会导致重要城市之间两两不连通。如果外敌无论如何都不可能导致这种局面,输出-1
Input
Output
Sample Input1
1 3
2 3
4 3
4
2 1 2
3 2 3 4
3 1 2 4
4 1 2 3 4
Sample Output1
-1
1
-1
Sample Input2
1 2
2 3
3 4
1 5
5 6
5 7
1
4 2 4 6 7
Sample Output2
2
Solution
$LCA$写错身败名裂了啊QAQ……
先建个虚树,然后特判掉无解,也就是有两个关键点相邻的情况。
判完无解后$DP$,设$F[i]$表示解决$i$子树的最小花费,$G[i]$表示$i$子树中还没有被阻断的点数。
具体转移看代码吧,也挺好懂的……
Code
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
#define N (100009)
using namespace std; struct Edge{int to,next;}edge[N<<];
int n,u,v,m,k,dfs_num,flag;
int a[N],DFN[N],Depth[N],f[N][],vis[N],F[N],G[N];
int head[N],num_edge; void add(int u,int v)
{
edge[++num_edge].to=v;
edge[num_edge].next=head[u];
head[u]=num_edge;
} void DFS(int x,int fa)
{
f[x][]=fa;
for (int i=; i<=; ++i)
f[x][i]=f[f[x][i-]][i-];
DFN[x]=++dfs_num; Depth[x]=Depth[fa]+;
for (int i=head[x]; i; i=edge[i].next)
if (edge[i].to!=fa) DFS(edge[i].to,x);
} int LCA(int x,int y)
{
if (Depth[x]<Depth[y]) swap(x,y);
for (int i=; i>=; --i)
if (Depth[f[x][i]]>=Depth[y]) x=f[x][i];
if (x==y) return x;
for (int i=; i>=; --i)
if (f[x][i]!=f[y][i]) x=f[x][i], y=f[y][i];
return f[x][];
} struct E{int to,next;}EDGE[N<<];
int HEAD[N],NUM_EDGE;
int stack[N],top;
bool cmp(int u,int v) {return DFN[u]<DFN[v];} void ADD(int u,int v)
{
if (u==v) return;
EDGE[++NUM_EDGE].to=v;
EDGE[NUM_EDGE].next=HEAD[u];
HEAD[u]=NUM_EDGE;
} void Insert(int x)
{
if (top==) {stack[++top]=x; return;}
int lca=LCA(x,stack[top]);
if (lca==stack[top]) {stack[++top]=x; return;}
while (top> && DFN[stack[top-]]>=DFN[lca])
ADD(stack[top-],stack[top]), top--;
if (lca!=stack[top]) ADD(lca,stack[top]), stack[top]=lca;
stack[++top]=x;
} void Build()
{
NUM_EDGE=; stack[top=]=;
for (int i=; i<=k; ++i)
Insert(a[i]);
while (top>=) ADD(stack[top-],stack[top]), top--;
} void DP(int x)
{
F[x]=; G[x]=;
for (int i=HEAD[x]; i; i=EDGE[i].next)
{
int y=EDGE[i].to; DP(y);
F[x]+=F[y]; G[x]+=G[y];
}
if (!vis[x]) F[x]+=(G[x]>), G[x]=(G[x]==);
else F[x]+=G[x], G[x]=;
} void Clear(int x)
{
vis[x]=false; F[x]=G[x]=;
for (int i=HEAD[x]; i; i=EDGE[i].next)
Clear(EDGE[i].to);
HEAD[x]=;
} int main()
{
scanf("%d",&n);
for (int i=; i<=n-; ++i)
{
scanf("%d%d",&u,&v);
add(u,v); add(v,u);
}
DFS(,);
scanf("%d",&m);
for (int i=; i<=m; ++i)
{
scanf("%d",&k);
for (int j=; j<=k; ++j)
scanf("%d",&a[j]), vis[a[j]]=true;
sort(a+,a+k+,cmp); flag=;
for (int j=; j<=k; ++j)
if (vis[a[j]] && vis[f[a[j]][]]) {flag=false; break;}
Build();
if (flag) DP(), printf("%d\n",F[]);
else puts("-1");
Clear();
}
}
CF613D:Kingdom and its Cities(树形DP,虚树)的更多相关文章
- 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分
树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...
- 【CF809E】Surprise me! 树形DP 虚树 数学
题目大意 给你一棵\(n\)个点的树,每个点有权值\(a_i\),\(a\)为一个排列,求 \[ \frac{1}{n(n-1)}\sum_{i=1}^n\sum_{j=1}^n \varphi(a_ ...
- 3611: [Heoi2014]大project|树形DP|虚树
构建出虚树然后DP统计答案 自己写的DP太傻QAQ,各种WA 膜了一发PoPoQQQ大爷的DP方法 mxdis,mndis分别表示到当前点近期和最远的被选出来的点的距离 mx,mn分别表示在以当前点为 ...
- BZOJ3611:[HEOI2014]大工程(树形DP,虚树)
Description 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上. 在 2 个国家 a,b 之间建一条新通 ...
- BZOJ2286:[SDOI2011]消耗战(树形DP,虚树)
Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总部在编号为1的岛屿,而且他们已经没有足够多的能源维系战斗,我军 ...
- 【BZOJ-1040】骑士 树形DP + 环套树 + DFS
1040: [ZJOI2008]骑士 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3312 Solved: 1269[Submit][Status ...
- HDU 4514 - 湫湫系列故事——设计风景线 - [并查集判无向图环][树形DP求树的直径]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4514 Time Limit: 6000/3000 MS (Java/Others) Memory Li ...
- 浅谈关于树形dp求树的直径问题
在一个有n个节点,n-1条无向边的无向图中,求图中最远两个节点的距离,那么将这个图看做一棵无根树,要求的即是树的直径. 求树的直径主要有两种方法:树形dp和两次bfs/dfs,因为我太菜了不会写后者这 ...
- 树形DP 学习笔记(树形DP、树的直径、树的重心)
前言:寒假讲过树形DP,这次再复习一下. -------------- 基本的树形DP 实现形式 树形DP的主要实现形式是$dfs$.这是因为树的特殊结构决定的——只有确定了儿子,才能决定父亲.划分阶 ...
随机推荐
- JS权威指南笔记之数据类型
1.类型分为原始类型和对象. 2.原始类型有:数字类型,字符类型,布尔,和null undefind. 3.JavaScript里的函数都是真值. 4.函数和通过New关键字创建对象.这个样函数称为构 ...
- MySQL 学习 --- 数据结构和索引
本文参考了多篇文章集成的笔记,希望各位学习之前可以阅读以下参考资料先 概述 文章分几个部分 :第一部分介绍了B-Tree 和 B+Tree 这种数据结构作为索引:第二部分介绍索引的最左前缀原则和覆盖索 ...
- SQLSERVER查询整个数据库中某个特定值所在的表和字段的方法
这几天有业务部门需要使用一个SAP B1老系统 中的报表,但是由于此报表没有加时间条件,导致一旦开始查询 就会导致B1系统异常退出.由于报表对应的SQL 是存在数据库中,所以想通过查找到这个报表的S ...
- nc63 树管理型单据的开发
<?xml version="1.0" encoding="gbk"?><beans xmlns="http://www.sprin ...
- 简单说说SpringMVC
距离上一次开发SpringMVC项目已经过去了大半年,有些细节已经开始遗忘,今天复习一下 先从标签说起: 和struts有各种配置文件不同,spring用标签开发. 1.@Controller在Spr ...
- fzu 2132 LQX的作业
Problem 2132 LQX的作业 Accept: 67 Submit: 150Time Limit: 1000 mSec Memory Limit : 32768 KB Proble ...
- 穿过代理获取真正的IP
/// <summary> /// 获取真ip /// </summary> /// <returns></returns> public string ...
- MQ与Webservice的区别
Webservice 和MQ(MessageQueue)都是解决跨平台通信的常用手段,两者有哪些区别呢? 个人认为最本质的区别在于 Webservice近乎实时通信,而MQ却通常是延时通信. 什么意思 ...
- HTML的代码规范
一.语法 用两个空格来代替制表符(tab) 2.嵌套元素应当缩进一次(即两个空格). 3.对于属性的定义,确保全部使用双引号,绝不要使用单引号. 4.不要省略可选的结束标签(例如,</li> ...
- web页面超时自动退出方法
思路: 使用 mousemover 事件来监测是否有用户操作页面,写一个定时器间隔特定时间检测是否长时间未操作页面,如果是,退出: 具体时间代码如下(js):var lastTime = new Da ...