Codeforces Round #613 Div.1 D.Kingdom and its Cities 贪心+虚树
题目链接:http://codeforces.com/contest/613/problem/D
题意概述:
给出一棵树,每次询问一些点,计算最少删除几个点可以让询问的点两两不连通,无解输出-1。保证询问的点总数不大于300000。
分析:
先考虑遍历的做法,统计每个点代表的子树中联通询问点的数量。
这个点不是询问点:如果有至少两个不同的子树中有询问点那么当前点一定被删除,因为这个时候不删除之后这两个点就是联通的;同时除了在更深的地方遇见第一种情况之外没有必要删除那些点;没有点不用管,只有一个点返回1。
这个点是询问点:每有一颗子树中有儿子就删除掉一个点。
判断无解:树上两个相邻的点都是询问点。
然后建立虚树在上面跑这个算法就可以了,减少无谓遍历的点的数量。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<cctype>
using namespace std;
const int maxn=; int N,Q;
struct edge{ int to,next; }E[maxn<<];
int first[maxn],np,fa[maxn][],dep[maxn],s[maxn],s_top;
int dfn[maxn],dfs_clock,stk[maxn],top,use[maxn],u_top;
bool inq[maxn];
struct vTree{
static const int maxnode=;
int first[maxnode],np,ans; bool vis[maxnode];
edge E[maxnode<<];
vTree(){
memset(first,,sizeof(first));
np=ans=;
memset(vis,,sizeof(vis));
}
void add_edge(int u,int v){
E[++np]=(edge){v,first[u]};
first[u]=np;
}
int DFS(int i,int f){
int cnt=;
for(int p=first[i];p;p=E[p].next){
int j=E[p].to;
if(j==f) continue;
if(DFS(j,i)){
if(vis[i]) ans++;
else cnt++;
}
}
if(vis[i]) return ;
if(cnt>){ ans++; return ; }
return cnt;
}
}vt; void _scanf(int &x)
{
x=;
char ch=getchar();
while(ch<''||ch>'') ch=getchar();
while(ch>=''&&ch<='') x=x*+ch-'',ch=getchar();
}
int out_cnt; char out[];
void _printf(int x)
{
if(x<) putchar('-'),x=-x;
out[++out_cnt]=x%+'',x/=;
while(x) out[++out_cnt]=x%+'',x/=;
while(out_cnt) putchar(out[out_cnt--]);
putchar('\n');
}
void add_edge(int u,int v)
{
E[++np]=(edge){v,first[u]};
first[u]=np;
}
void data_in()
{
_scanf(N);
int x,y;
for(int i=;i<N;i++){
_scanf(x);_scanf(y);
add_edge(x,y); add_edge(y,x);
}
_scanf(Q);
}
void ready(int i,int f,int d)
{
fa[i][]=f,dep[i]=d,dfn[i]=++dfs_clock;
for(int j=;(<<j)<d;j++)
fa[i][j]=fa[fa[i][j-]][j-];
for(int p=first[i];p;p=E[p].next){
if(E[p].to==f) continue;
ready(E[p].to,i,d+);
}
}
int LCA(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
int len=dep[x]-dep[y];
for(int i=;(<<i)<=len;i++)
if((<<i)&len) x=fa[x][i];
if(x==y) return x;
for(int i=;i>=;i--)
if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return fa[x][];
}
bool cmp(int x,int y) { return dfn[x]<dfn[y]; }
void build_vt()
{
stk[++top]=,inq[]=,use[++u_top]=;
if(s[]!=) stk[++top]=s[],inq[s[]]=,use[++u_top]=s[];
for(int j=;j<=s_top;j++){
int z=LCA(s[j],s[j-]);
while(top>&&dep[stk[top-]]>dep[z]){
vt.add_edge(stk[top-],stk[top]);
vt.add_edge(stk[top],stk[top-]);
top--;
}
if(top&&dep[stk[top]]>dep[z]){
vt.add_edge(stk[top],z);
vt.add_edge(z,stk[top]);
top--;
}
if(!inq[z]) inq[z]=,stk[++top]=z,use[++u_top]=z;
if(!inq[s[j]]) inq[s[j]]=,stk[++top]=s[j],use[++u_top]=s[j];
}
while(top>){
vt.add_edge(stk[top-],stk[top]);
vt.add_edge(stk[top],stk[top-]);
top--;
}
top=;
}
void work()
{
ready(,,);
int k,x;
for(int i=;i<=Q;i++){
_scanf(k);
for(int j=;j<=k;j++){
_scanf(x);
s[++s_top]=x,vt.vis[x]=;
}
bool ok=;
for(int j=;j<=s_top;j++)
if(vt.vis[fa[s[j]][]]){ ok=; break; }
if(!ok) _printf(-);
else{
sort(s+,s+s_top+,cmp);
build_vt();
vt.DFS(,);
_printf(vt.ans);
}
while(s_top) vt.vis[s[s_top--]]=;
while(u_top) inq[use[u_top]]=,vt.first[use[u_top]]=,u_top--;
vt.np=vt.ans=;
}
}
int main()
{
data_in();
work();
return ;
}
Codeforces Round #613 Div.1 D.Kingdom and its Cities 贪心+虚树的更多相关文章
- 【CF613D】Kingdom and its Cities(虚树,动态规划)
[CF613D]Kingdom and its Cities(虚树,动态规划) 题面 洛谷 CF 翻译洛谷上有啦 题解 每次构建虚树,首先特判无解,也就是关键点中存在父子关系. 考虑\(dp\),设\ ...
- Codeforces Round #367 (Div. 2) D. Vasiliy's Multiset (0/1-Trie树)
Vasiliy's Multiset 题目链接: http://codeforces.com/contest/706/problem/D Description Author has gone out ...
- Codeforces Round #538 (Div. 2) F 欧拉函数 + 区间修改线段树
https://codeforces.com/contest/1114/problem/F 欧拉函数 + 区间更新线段树 题意 对一个序列(n<=4e5,a[i]<=300)两种操作: 1 ...
- CodeForces - 613D:Kingdom and its Cities(虚树+DP)
Meanwhile, the kingdom of K is getting ready for the marriage of the King's daughter. However, in or ...
- Codeforces Round #613 (Div. 2) A-E简要题解
contest链接:https://codeforces.com/contest/1285 A. Mezo Playing Zoma 签到 #include<iostream> #incl ...
- Codeforces Round #613 (Div. 2) (A-E)
A略 直接求和最大的子序列即可(注意不能全部选中整个子序列) or #include<bits/stdc++.h> using namespace std; void solve(){ i ...
- Codeforces Round #613 (Div. 2)D(贪心,分治)
构造两颗深度为30的字典树(根节点分别是0和1),结点只有0和1,从根节点向下DFS,贪心取答案. #define HAVE_STRUCT_TIMESPEC #include<bits/stdc ...
- Codeforces Round #613 (Div. 2) C. Fadi and LCM(LCM & GCD)
题意: LCM(a, b) = X,求 max(a, b) 的最小值. 思路: a, b 只可能存在于 X 的因子中,枚举即可. #include <bits/stdc++.h> usin ...
- Codeforces Round #613 (Div. 2) B. Just Eat It!(前缀和)
题意: 一个长为n的序列,是否存在与原序列不同的连续子序列,其元素之和大于等于原序列. 思路: 从前.后分别累加,若出现非正和,除此累加序列外的子序列元素之和一定大于等于原序列. #include & ...
随机推荐
- 面试官问你JS基本类型时他想知道什么?
面试的时候我们经常会被问答js的数据类型.大部分情况我们会这样回答包括:1.基本类型(值类型或者原始类型): Number.Boolean.String.NULL.Undefined以及ES6的Sym ...
- ios开发UI篇—UISlider
概述 UISlider用于从连续范围的值中选择单个值的控件. 当您移动滑块的大拇指时,会将其更新后的值传递给附加的任何动作.滑块的外观是可配置的; 您可以对曲目和大拇指进行着色,并提供出现在滑块末端的 ...
- 基于 HTML5 Canvas 的拓扑组件开发
在现在前端圈大行其道的 React 和 Vue 中,可复用的组件可能是他们大受欢迎的原因之一, 在 HT 的产品中也有组件的概念,不过在 HT 中组件的开发是依托于 HTML5 Canvas 的技术去 ...
- 树莓3B+_apt-get update && apt-get upgrade
在Windows下安装软件,我们只需要有EXE文件,然后双击,下一步直接OK就可以了.但在LINUX下,不是这样的.每个LINUX的发行版,都会维护一个自己的软件仓库,我们常用的几乎所有软件都在这里面 ...
- 多线程深入理解和守护线程、子线程、锁、queue、evenet等介绍
1.多线程类的继承 import threading import time class MyThreading(threading.Thread): def __init__(self,n): su ...
- PTA基础编程题目集6-2多项式求值(函数题)
本题要求实现一个函数,计算阶数为n,系数为a[0] ... a[n]的多项式f(x)=∑i=0n(a[i]×xi) 在x点的值. 函数接口定义: double f( int n, dou ...
- 《Java核心技术36讲》阅读笔记:Exception和Error有什么区别?
1.Exception 和 Error有什么区别?运行时异常与一般异常有什么区别? Exception和Error都继承自java.lang.Throwable.在Java中只有Throwable的实 ...
- SVG中嵌入HTML元素
<?xml version="1.0" standalone="yes"?> <style> .clsfont{ border:1px ...
- 20155217 2016-2017-2 《Java程序设计》第6周学习总结
20155217 2016-2017-2 <Java程序设计>第6周学习总结 教材学习内容总结 第十章 InputStream与OutputStream 10.1.1串流设计的概念 Jav ...
- 20155217 2016-2017-2《java程序设计》第一周学习总结
20155217 2016-2017-2<java程序设计>第一周学习总结 浏览教材,根据自己的理解每章提出一个问题 java平台和java编程语言的区别? 怎样使用IDE来管理原始码与位 ...