传送门


$\sum k \leq 100000$虚树套路题

设$f_{i,0/1}$表示处理完$i$以及其所在子树的问题,且处理完后$i$所在子树内是否存在$1$个关键点满足它到$i$的路径上不存在任何点被封的最小代价。

转移考虑$i$是否是关键点以及是否封$i$号点。

注意判断相邻两个点同时是关键点的情况。同时需要注意:如果虚树上两个点不相邻,可以封这两个点之间的点。

 #include<bits/stdc++.h>
 //This code is written by Itst
 using namespace std;

 inline int read(){
     ;
     ;
     char c = getchar();
     while(c != EOF && !isdigit(c)){
         if(c == '-')
             f = ;
         c = getchar();
     }
     while(c != EOF && isdigit(c)){
         a = (a << ) + (a << ) + (c ^ ');
         c = getchar();
     }
     return f ? -a : a;
 }

 ;
 struct Edge{
     int end , upEd;
 }Ed[MAXN << ] , newEd[MAXN];
 ] , newHead[MAXN] , s[MAXN] , dfn[MAXN] , num[MAXN] , dp[MAXN][] , dep[MAXN];
 int N , headS , cntEd , cntNewEd , ts , cnt;
 bool imp[MAXN];

 inline void addEd(Edge* Ed , int* head , int& cntEd , int a , int b){
     Ed[++cntEd].end = b;
     Ed[cntEd].upEd = head[a];
     head[a] = cntEd;
 }

 void init(int now , int fa){
     dfn[now] = ++ts;
     dep[now] = dep[fa] + ;
     jump[now][] = fa;
      ; jump[now][i - ] ; ++i)
         jump[now][i] = jump[jump[now][i - ]][i - ];
     for(int i = head[now] ; i ; i = Ed[i].upEd)
         if(Ed[i].end != fa)
             init(Ed[i].end , now);
 }

 inline int jumpToLCA(int x , int y){
     if(dep[x] < dep[y])
         swap(x , y);
      ; i >=  ; --i)
          << i) >= dep[y])
             x = jump[x][i];
     if(x == y)
         return x;
      ; i >=  ; --i)
         if(jump[x][i] != jump[y][i]){
             x = jump[x][i];
             y = jump[y][i];
         }
     ];
 }

 inline void create(){
     imp[] = ;
     dp[][] = dp[][] = ;
      ; i <= cnt ; ++i){
         imp[num[i]] = ;
         dp[num[i]][] = ;
         dp[num[i]][] = N + ;
     }
      ; i <= cnt ; ++i)
         if(!headS)
             s[++headS] = num[i];
         else{
             int t = jumpToLCA(s[headS] , num[i]);
             if(t != s[headS]){
                 ]] > dep[t]){
                     addEd(newEd , newHead , cntNewEd , s[headS - ] , s[headS]);
                     --headS;
                 }
                 addEd(newEd , newHead , cntNewEd , t , s[headS]);
                 if(s[--headS] != t)
                     s[++headS] = t;
             }
             s[++headS] = num[i];
         }
     ){
         addEd(newEd , newHead , cntNewEd , s[headS - ] , s[headS]);
         --headS;
     }
     )
         addEd(newEd , newHead , cntNewEd ,  , s[headS]);
     --headS;
 }

 void dfs(int now){
     ;
     for(int i = newHead[now] ; i ; i = newEd[i].upEd){
         int t = newEd[i].end;
         dfs(t);
         if(imp[now])
             ] == now)
                 dp[now][] += dp[t][];
             else
                 dp[now][] += min(dp[t][] , dp[t][] + );
         else{
             ] == now)
                 dp[now][] = min(sum + dp[t][] , dp[now][] + dp[t][]);
             else
                 dp[now][] = min(sum + dp[t][] , dp[now][] + min(dp[t][] , dp[t][] + ));
             ] == now)
                 sum += dp[t][];
             else
                 sum += min(dp[t][] , dp[t][] + );
         }
         ] > N)
             dp[now][] = N + ;
         )
             sum = N + ;
     }
     sum = ;
     for(int i = newHead[now] ; i ; i = newEd[i].upEd){
         int t = newEd[i].end;
         if(!imp[now]){
             sum += min(dp[t][] , dp[t][]);
             dp[now][] += dp[t][];
         }
         dp[t][] = dp[t][] = imp[t] = ;
     }
     if(!imp[now])
         dp[now][] = min(dp[now][] , sum + );
     newHead[now] = ;
 }

 bool cmp(int a , int b){
     return dfn[a] < dfn[b];
 }

 int main(){
 #ifndef ONLINE_JUDGE
     freopen("613D.in" , "r" , stdin);
     //freopen("613D.out" , "w" , stdout);
 #endif
     N = read();
      ; i < N ; ++i){
         int a = read() , b = read();
         addEd(Ed , head , cntEd , a , b);
         addEd(Ed , head , cntEd , b , a);
     }
     init( , );
     for(int M = read() ; M ; --M){
         cnt = read();
          ; i <= cnt ; ++i)
             num[i] = read();
         sort(num +  , num + cnt +  , cmp);
         create();
         dfs();
         ][] , dp[][]);
         printf( ? - : t);
     }
     ;
 }

CF613D Kingdom and its Cities 虚树的更多相关文章

  1. CF613D Kingdom and its Cities 虚树 树形dp 贪心

    LINK:Kingdom and its Cities 发现是一个树上关键点问题 所以考虑虚树刚好也有标志\(\sum k\leq 100000\)即关键点总数的限制. 首先当k==1时 答案显然为0 ...

  2. CF613D Kingdom and its Cities 虚树 + 树形DP

    Code: #include<bits/stdc++.h> #define ll long long #define maxn 300003 #define RG register usi ...

  3. 【CF613D】Kingdom and its Cities 虚树+树形DP

    [CF613D]Kingdom and its Cities 题意:给你一棵树,每次询问给出k个关键点,问做多干掉多少个非关键点才能使得所有关键点两两不连通. $n,\sum k\le 10^5$ 题 ...

  4. CF613D:Kingdom and its Cities(树形DP,虚树)

    Description 一个王国有n座城市,城市之间由n-1条道路相连,形成一个树结构,国王决定将一些城市设为重要城市. 这个国家有的时候会遭受外敌入侵,重要城市由于加强了防护,一定不会被占领.而非重 ...

  5. CF613D Kingdom and its Cities(虚树+贪心)

    很休闲的一个题啊 其实一看到关于\(\sum k\)的限制,就知道是个虚树的题了 首先我们把虚树建出来,然后考虑怎么计算个数呢? 我们令\(f[x]\)表示以\(x\)的子树中,剩余了多少个还没有切断 ...

  6. [CF613D]Kingdom and its Cities

    description 题面 data range \[n, q,\sum k\le 10^5\] solution 还是虚树的练手题 \(f[0/1][u]\)表示\(u\)的子树内,\(u\)是否 ...

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

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

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

  9. Codeforces Round #613 Div.1 D.Kingdom and its Cities 贪心+虚树

    题目链接:http://codeforces.com/contest/613/problem/D 题意概述: 给出一棵树,每次询问一些点,计算最少删除几个点可以让询问的点两两不连通,无解输出-1.保证 ...

随机推荐

  1. 图中最短路径的算法--dijiska算法C语言实现

    #include <stdio.h> #include <stdlib.h> #define ERROR_NO_MEM -1 /*内存不足的错误码*/ #define MAX_ ...

  2. Telephone dialer

    运行电话拨号器,需要加这个权限,否则不会打通电话.这个权限是用户权限,是谷歌工程师为了跟自己撇清关系,用户需要权限的时候自己加. 运行android程序的时候提示:ActivityManager: W ...

  3. 安装Django(1)

    安装Django 注意:因为这是web项目将来要部署在Linux上,所以使用centos/ubuntu:因为Python3是将来的趋势,所以使用Python3做为开发语言.本人使用的开发模式操作系统: ...

  4. UML类图关系图解

    一.类结构 在类的UML图中,使用长方形描述一个类的主要构成,长方形垂直地分为三层,以此放置类的名称.属性和方法. 其中, 一般类的类名用正常字体粗体表示,如上图:抽象类名用斜体字粗体,如User:接 ...

  5. 《R数据挖掘入门》彩色插图(第8章)

    图8.4 图8.5 图8.6 图8.7

  6. 02-OpenLDAP配置

    OpenLDAP配置 在OpenLDAP 2.4版本中,配置OpenLDAP的方法有两种:一种通过修改配置文件实现配置,另一种通过修改数据库的形式完成配置. 通过配置数据库完成各种配置,属于动态配置且 ...

  7. rsync远程同步的基本配置与使用

    rsync是一个开源的快速备份工具,可以在不同主机之间镜像同步整个目录树,支持增量备份,保持链接和权限,且采用优化的同步算法,传输前执行压缩,因此非常适用于异地备份,镜像服务器等应用. rsync的官 ...

  8. beta版本汇总

    deta版本五天汇总 day1 day2 day3 day4 day5 GitHub地址 前端代码github地址 后端代码github地址 这里说明一下我们队伍的安排风格: 第一天:明确安排前后端的 ...

  9. python框架面试题联系

    1.对 MVC,MVT 解读的理解? M:Model,模型,和数据库进行交互 V:View,视图,负责产生 Html 页面 C:Controller,控制器,接收请求,进行处理,与 M 和 V 进行交 ...

  10. python scrapy 登录知乎过程

    前面了解了scrapy框架的大概各个组件的作用, 现在要爬取知乎数据,那么第一步就是要登录! 看下知乎的登录页面发现登录主要是两大接口 一: 登录页面地址,获取登录需要的验证码,如下图 打开知乎登录页 ...