CF613D Kingdom and its Cities 虚树

Posted itst

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF613D Kingdom and its Cities 虚树相关的知识,希望对你有一定的参考价值。

传送门


 

$sum k leq 100000$虚树套路题

设$f_{i,0/1}$表示处理完$i$以及其所在子树的问题,且处理完后$i$点存在$0/1$个没有被封住的关键点时的最小代价,转移考虑$i$是否是关键点,随便转就行了

  1 #include<bits/stdc++.h>
  2 //This code is written by Itst
  3 using namespace std;
  4 
  5 inline int read(){
  6     int a = 0;
  7     bool f = 0;
  8     char c = getchar();
  9     while(c != EOF && !isdigit(c)){
 10         if(c == -)
 11             f = 1;
 12         c = getchar();
 13     }
 14     while(c != EOF && isdigit(c)){
 15         a = (a << 3) + (a << 1) + (c ^ 0);
 16         c = getchar();
 17     }
 18     return f ? -a : a;
 19 }
 20 
 21 const int MAXN = 100010;
 22 struct Edge{
 23     int end , upEd;
 24 }Ed[MAXN << 1] , newEd[MAXN];
 25 int head[MAXN] , jump[MAXN][20] , newHead[MAXN] , s[MAXN] , dfn[MAXN] , num[MAXN] , dp[MAXN][2] , dep[MAXN];
 26 int N , headS , cntEd , cntNewEd , ts , cnt;
 27 bool imp[MAXN];
 28 
 29 inline void addEd(Edge* Ed , int* head , int& cntEd , int a , int b){
 30     Ed[++cntEd].end = b;
 31     Ed[cntEd].upEd = head[a];
 32     head[a] = cntEd;
 33 }
 34 
 35 void init(int now , int fa){
 36     dfn[now] = ++ts;
 37     dep[now] = dep[fa] + 1;
 38     jump[now][0] = fa;
 39     for(int i = 1 ; jump[now][i - 1] ; ++i)
 40         jump[now][i] = jump[jump[now][i - 1]][i - 1];
 41     for(int i = head[now] ; i ; i = Ed[i].upEd)
 42         if(Ed[i].end != fa)
 43             init(Ed[i].end , now);
 44 }
 45 
 46 inline int jumpToLCA(int x , int y){
 47     if(dep[x] < dep[y])
 48         swap(x , y);
 49     for(int i = 19 ; i >= 0 ; --i)
 50         if(dep[x] - (1 << i) >= dep[y])
 51             x = jump[x][i];
 52     if(x == y)
 53         return x;
 54     for(int i = 19 ; i >= 0 ; --i)
 55         if(jump[x][i] != jump[y][i]){
 56             x = jump[x][i];
 57             y = jump[y][i];
 58         }
 59     return jump[x][0];
 60 }
 61 
 62 inline void create(){
 63     imp[1] = 0;
 64     dp[1][0] = dp[1][1] = 0;
 65     for(int i = 1 ; i <= cnt ; ++i){
 66         imp[num[i]] = 1;
 67         dp[num[i]][1] = 0;
 68         dp[num[i]][0] = N + 1;
 69     }
 70     for(int i = 1 ; i <= cnt ; ++i)
 71         if(!headS)
 72             s[++headS] = num[i];
 73         else{
 74             int t = jumpToLCA(s[headS] , num[i]);
 75             if(t != s[headS]){
 76                 while(dep[s[headS - 1]] > dep[t]){
 77                     addEd(newEd , newHead , cntNewEd , s[headS - 1] , s[headS]);
 78                     --headS;
 79                 }
 80                 addEd(newEd , newHead , cntNewEd , t , s[headS]);
 81                 if(s[--headS] != t)
 82                     s[++headS] = t;
 83             }
 84             s[++headS] = num[i];
 85         }
 86     while(headS - 1){
 87         addEd(newEd , newHead , cntNewEd , s[headS - 1] , s[headS]);
 88         --headS;
 89     }
 90     if(s[headS] != 1)
 91         addEd(newEd , newHead , cntNewEd , 1 , s[headS]);
 92     --headS;
 93 }
 94 
 95 void dfs(int now){
 96     int sum = 0;
 97     for(int i = newHead[now] ; i ; i = newEd[i].upEd){
 98         int t = newEd[i].end;
 99         dfs(t);
100         if(imp[now])
101             if(jump[t][0] == now)
102                 dp[now][1] += dp[t][0];
103             else
104                 dp[now][1] += min(dp[t][0] , dp[t][1] + 1);
105         else{
106             if(jump[t][0] == now)
107                 dp[now][1] = min(sum + dp[t][1] , dp[now][1] + dp[t][0]);
108             else
109                 dp[now][1] = min(sum + dp[t][1] , dp[now][1] + min(dp[t][0] , dp[t][1] + 1));
110             if(jump[t][0] == now)
111                 sum += dp[t][0];
112             else
113                 sum += min(dp[t][0] , dp[t][1] + 1);
114         }
115         if(dp[now][1] > N)
116             dp[now][1] = N + 1;
117         if(sum > N + 1)
118             sum = N + 1;
119     }
120     sum = 0;
121     for(int i = newHead[now] ; i ; i = newEd[i].upEd){
122         int t = newEd[i].end;
123         if(!imp[now]){
124             sum += min(dp[t][0] , dp[t][1]);
125             dp[now][0] += dp[t][0];
126         }
127         dp[t][0] = dp[t][1] = imp[t] = 0;
128     }
129     if(!imp[now])
130         dp[now][0] = min(dp[now][0] , sum + 1);
131     newHead[now] = 0;
132 }
133 
134 bool cmp(int a , int b){
135     return dfn[a] < dfn[b];
136 }
137 
138 int main(){
139 #ifndef ONLINE_JUDGE
140     freopen("613D.in" , "r" , stdin);
141     //freopen("613D.out" , "w" , stdout);
142 #endif
143     N = read();
144     for(int i = 1 ; i < N ; ++i){
145         int a = read() , b = read();
146         addEd(Ed , head , cntEd , a , b);
147         addEd(Ed , head , cntEd , b , a);
148     }
149     init(1 , 0);
150     for(int M = read() ; M ; --M){
151         cnt = read();
152         for(int i = 1 ; i <= cnt ; ++i)
153             num[i] = read();
154         sort(num + 1 , num + cnt + 1 , cmp);
155         create();
156         dfs(1);
157         int t = min(dp[1][0] , dp[1][1]);
158         printf("%d
" , t == N + 1 ? -1 : t);
159     }
160     return 0;
161 }

以上是关于CF613D Kingdom and its Cities 虚树的主要内容,如果未能解决你的问题,请参考以下文章

CF613D Kingdom and its Cities

CF613D Kingdom and its Cities 虚树

题解 CF613D Kingdom and its Cities

codeforces 613D:Kingdom and its Cities

CodeForces - 613D:Kingdom and its Cities(虚树+DP)

CF613DKingdom and its Cities 虚树+树形DP