题目链接: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. async函数结合promise的小案例

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. python制作验证码

    from PIL import Image, ImageFont, ImageDraw, ImageFilterfrom random import choice, randint # 随即配置颜色d ...

  3. MySQL 基础小技巧

    把MySQL软件制作成系统服务 .把mysqld软件做成系统服务 注意:制作之前先把mysqld关掉 C:\Windows\system32>tasklist |findstr mysqld m ...

  4. Phaser3 对象池随机产生炸弹并销毁

    效果图 对象池 Object Pool scene.js /// <reference path="../../libs/phaser/phaser.min.js"/> ...

  5. gi的安装和使用

    Git的安装 git是什么? git是一种版本控制器,更直白的说,团队开发的时候,管理代码使用的软件 Linux下的安装 yum install git Git的配置 在使用git之前,需要先进行配置 ...

  6. 20155207第二周myod以及课堂测试

    第二周myod以及课堂测试 第二周测试5 题目 1.除了main.c外,其他4个模块(add.c sub.c mul.c div.c)的源代码不想给别人,如何制作一个mymath.so共享库?main ...

  7. 初步安装配置虚拟机、Ubuntu、git、vim、码云项目

    内容 虚拟机软件:Oracle VM VirtualBox 系统:Ubuntu 配置:git:码云;vim 过程 下载安装VirtualBox.ubuntu 根据链接-- 基于VirtualBox安装 ...

  8. BZOJ054_移动玩具_KEY

    题目传送门 这道题我写IDA*写挂了,TLE+WA,只AC了两个点. 这道题标算BFS+状态压缩. code: /******************************************* ...

  9. 简单读取 properties文件

    看了网上很多读取的方法,都太过复杂,直接使用下面的方法就可以简单读取 properties文件了 ide使用idea 测试读取成功 import java.util.ResourceBundle; p ...

  10. 【转】 mysql使用federated引擎实现远程访问数据库(跨网络同时操作两个数据库中的表)

    原文转自:http://www.2cto.com/database/201412/358397.html 问题: 这里假设我需要在IP1上的database1上访问IP2的database数据库内的t ...