题目链接: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 贪心+虚树的更多相关文章

  1. 【CF613D】Kingdom and its Cities(虚树,动态规划)

    [CF613D]Kingdom and its Cities(虚树,动态规划) 题面 洛谷 CF 翻译洛谷上有啦 题解 每次构建虚树,首先特判无解,也就是关键点中存在父子关系. 考虑\(dp\),设\ ...

  2. 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 ...

  3. Codeforces Round #538 (Div. 2) F 欧拉函数 + 区间修改线段树

    https://codeforces.com/contest/1114/problem/F 欧拉函数 + 区间更新线段树 题意 对一个序列(n<=4e5,a[i]<=300)两种操作: 1 ...

  4. 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 ...

  5. Codeforces Round #613 (Div. 2) A-E简要题解

    contest链接:https://codeforces.com/contest/1285 A. Mezo Playing Zoma 签到 #include<iostream> #incl ...

  6. Codeforces Round #613 (Div. 2) (A-E)

    A略 直接求和最大的子序列即可(注意不能全部选中整个子序列) or #include<bits/stdc++.h> using namespace std; void solve(){ i ...

  7. Codeforces Round #613 (Div. 2)D(贪心,分治)

    构造两颗深度为30的字典树(根节点分别是0和1),结点只有0和1,从根节点向下DFS,贪心取答案. #define HAVE_STRUCT_TIMESPEC #include<bits/stdc ...

  8. 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 ...

  9. Codeforces Round #613 (Div. 2) B. Just Eat It!(前缀和)

    题意: 一个长为n的序列,是否存在与原序列不同的连续子序列,其元素之和大于等于原序列. 思路: 从前.后分别累加,若出现非正和,除此累加序列外的子序列元素之和一定大于等于原序列. #include & ...

随机推荐

  1. Java并发编程(九)线程间协作(下)

    上篇我们讲了使用wait()和notify()使线程间实现合作,这种方式很直接也很灵活,但是使用之前需要获取对象的锁,notify()调用的次数如果小于等待线程的数量就会导致有的线程会一直等待下去.这 ...

  2. python3爬虫-通过requests爬取图虫网

    import requests from fake_useragent import UserAgent from requests.exceptions import Timeout from ur ...

  3. 查看所装jdk版本

    在D盘新建一个test.java文件 在文件里写如下代码: public class test { public static void main(String[] args) { String ar ...

  4. 大数据:Windows下配置flink的Stream

    对于开发人员来说,最希望的是需要在windows中进行测试,然后把调试好的程序放在集群中运行.下面写一个Socket,上面是监控本地的一个运行端口,来实时的提取数据.获取视频中文档资料及完整视频的伙伴 ...

  5. 数据立方体(Cube)

    如上图所示,这是由三个维度构成的一个OLAP立方体,立方体中包含了满足条件的cell(子立方块)值,这些cell里面包含了要分析的数据,称之为度量值.显而易见,一组三维坐标唯一确定了一个子立方. 多位 ...

  6. git提交代码速度过慢解决方法(macos)

    iterm2中ping下github.com和github.global.ssl.fastly.net $ ping github.com 得到以下 PING github.com (192.30.2 ...

  7. Fiddler无所不能——之测试开发攻城狮必备利器

    Fiddler无所不能——之测试开发攻城狮必备利器 1.模拟真实网络环境4g网.3g网络.2g网络.弱网.请求超时 开启弱网Rules——Performance——勾选Simulate Modem S ...

  8. Python 1.3 元组与文件

    一 Python元组Tuple类型 元组T= (1, 2, 3, 4)是不可变类型,属于序列,但顶层元素不可变,仅支持count()和index()操作. -*- coding:UTF- -*- # ...

  9. python的MetaClass的代码分析。基于廖雪峰博客代码

    # 一张表一个类,表内每一行就是一个实例 ''' 一个单独的元类使用的程序分析. ''' class Field(object): def __init__(self, name, column_ty ...

  10. package html to native application

    npm install nw -g npm . https://github.com/nwjs/nw.js/ https://github.com/nwjs/nw.js/wiki/How-to-run ...