luogu P4426 [HNOI/AHOI2018]毒瘤 虛樹dp
題意
- 給你一個連通圖,求獨立集個數,滿足
這個題真的跟題目描述一樣毒瘤,網上的題解看了好久都看不懂,只能結合別人的程式碼邊抄邊想了。
首先在考場上有一個很優秀的暴力,我們把非樹邊提出來,暴力列舉非樹邊的選取狀態,可以做到
的複雜度,我們考慮優化這個暴力,可以發現,每次做
的樹形
的時候,很多點的轉移都是相同的,我們把所有非樹邊上的點定義為關鍵點,那麼我們建出所有關鍵點的虛樹之後,對於虛樹上的兩個點
,轉移可以寫成這樣的形式。
那麼現在我們要做的就是怎樣計算
,這個東西實際上我們進行一次
的
就可以計算出來,設
表示虛樹上
這個點,第一個
表示它自己選不選,第二個表示它要轉移到的那個點選不選,那麼我們每次提出虛樹中兩個點之間的鏈進行
即可,
的轉移和暴力是一樣的,這裡就不寫了。還有
值就是表示刪去虛樹兒子那些鏈後的值,
過的點也一定要標記,否則會算重。那我們按照原來那個方法在虛樹上
可以做到
複雜度,然後就做完了。
總結一下,首先建出虛樹,然後對於虛樹上每個點求出它往它父親的轉移係數,處理的時候要對於虛樹上的點要不包含虛樹上的兒子的 值,推出轉移係數之後直接暴力列舉加 就可以了
Codes
#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define x first
#define y second
using namespace std;
const int M = 10 + 8;
const int N = 1e5 + 10;
const int mod = 998244353;
vector<int> G[N];
pair<int, int> E[N];
map<int, bool> cut[N];
int to[N << 1], nxt[N << 1], head[N], e;
int fa[N][M], dep[N], st[N], ed[N], rel[N << 1], ban[N];
int tmp[N], ins[N], FA[N], f[N][2], k[N][2][2], dp[N][2];
int n, m, cnt, tot, dfn_cnt;
void add(int x, int y) {
if (!x || !y) return;
to[++ e] = y; nxt[e] = head[x]; head[x] = e;
}
int lca(int x, int y) {
if (dep[x] ^ dep[y]) {
if (dep[x] < dep[y]) swap(x, y);
for (int j = M - 1; ~j; -- j)
if (dep[fa[x][j]] > dep[y])
x = fa[x][j];
x = fa[x][0];
}
if (x ^ y) {
for (int j = M - 1; ~j; -- j)
if (fa[x][j] ^ fa[y][j])
x = fa[x][j], y = fa[y][j];
x = fa[x][0];
}
return x;
}
void dfs(int x, int dad) {
fa[x][0] = dad, rel[st[x] = ++ dfn_cnt] = x;
for (int j = 1; j < M; ++ j)
fa[x][j] = fa[fa[x][j - 1]][j - 1];
for (auto v : G[x]) if (v ^ dad) {
if (!st[v]) dep[v] = dep[x] + 1, dfs(v, x);
else if (st[v] < st[x])
E[++ cnt] = mp(x, v), cut[x][v] = cut[v][x] = 1;
}
rel[ed[x] = ++ dfn_cnt] = x;
}
void DP(int x, int no) {
f[x][0] = f[x][1] = 1, ins[x] = 1;
for (auto v : G[x]) if (v ^ fa[x][0] && v ^ no && !cut[x][v] && !ins[v]) {
DP(v, no), f[x][1] = 1ll * f[x][1] * f[v][0] % mod;
f[x][0] = 1ll * f[x][0] * (f[v][1] + f[v][0]) % mod;
}
}
void get_k(int x, int y) {
// k[x][0][0] x no choose i no choose
// k[x][0][1] x no choose i choose
// k[x][1][0] x choose i no choose
// k[x][1][1] x choose i choose
k[x][0][0] = k[x][1][1] = 1;
for (int i = x; fa[i][0] ^ y; i = fa[i][0]) {
int tp[2][2]; DP(fa[i][0], i);
tp[0][0] = 1ll * f[fa[i][0]][0] * (k[x][0][1] + k[x][0][0]) % mod;
tp[1][0] = 1ll * f[fa[i][0]][0] * (k[x][1][0] + k[x][1][1]) % mod;
tp[0][1] = 1ll * f[fa[i][0]][1] * k[x][0][0] % mod;
tp[1][1] = 1ll * f[fa[i][0]][1] * k[x][1][0] % mod;
swap(k[x], tp);
}
}
void DFS(int x) {
for (int i = head[x]; i; i = nxt[i]) DFS(to[i]), get_k(to[i], x);
f[x][0] = f[x][1] = 1;
for (auto v : G[x]) if (!cut[x][v] && v ^ fa[x][0] && !ins[v]) {
DP(v, 0), f[x][1] = 1ll * f[x][1] * f[v][0] % mod;
f[x][0] = 1ll * f[x][0] * (f[v][1] + f[v][0]) % mod;
}
}
void build() {
stack<int> S; tmp[tot = 1] = 1;
for (int i = 1; i <= cnt; ++ i)
tmp[++ tot] = st[E[i].x], tmp[++ tot] = st[E[i].y];
sort(tmp
相關推薦
luogu P4426 [HNOI/AHOI2018]毒瘤 虛樹dp
題意
給你一個連通圖,求獨立集個數,滿足
m
<
=
Luogu4426 HNOI2018/AHOI2018 毒瘤 虛樹
傳送門
如果原圖是一棵樹的話,很顯然就是統計獨立集數量,直接樹形$DP$就可以了。
但是原圖中又有額外的一些邊,這又要如何去做?
先在圖上摳出一棵樹,發現非樹邊的數量$delta \leq 11$,那麼——我們可以列舉每一條邊的兩個點的選取情況。
考慮到一共有三種情況:$(1,0)
Luogu P4425 [HNOI/AHOI2018]轉盤 線段樹
題意
一個轉盤上有
n
n
n個物品,每個物品有一個出現時間,你每次
[BZOJ5287][HNOI2018]毒瘤(虛樹DP)
暴力列舉非樹邊取值做DP可得75。
注意到每次枚舉出一個容斥狀態的時候,都要做大量重複操作。
建立虛樹,預處理出虛樹上兩點間的轉移係數。也可動態DP解決。
樹上倍增、動態DP、虛樹DP似乎是這種問題的三種通用解法。
程式碼不是特別長但極其難寫,預處理過程中要考慮各種情況。水平不夠只好抄程式碼。
luogu P4438 [HNOI/AHOI2018]道路 樹形dp
傳送門
講一下做題的過程
Day1 指定標籤搜尋 看題 從入門到入土
噁心 再見吧
Day2 這麼咕了一道題好像不好?還是做一下吧
10 minutes later……
這不就是個二叉樹嗎!
題意就是統計每個點經過的左右邊的路徑上選擇多少條邊進行標記
然後化成一個沒法巧算
[BZOJ3572][HNOI2014]世界樹(虛樹DP)
iostream ash char ios swa break sort 之前 題目 代碼用時1:15
思想比較簡單的虛樹DP,但細節巨茍,大部分代碼都是LCA/DP/虛樹模板,真正需要自己寫的其實並不多。
寫之前要有一個清晰的思路和框架,細節要有一個比較清楚的認識,不能依
【Bzoj2286】消耗戰(虛樹+DP)
swap mem cpp php down oid info LV algo Description
題目鏈接
Solution
在虛樹上跑DP即可
Code
#include <cstdio>
#include <algorithm>
#inclu
#10 //I [HNOI/AHOI2018]毒瘤
div 我們 ++ ack cin 一個點 mem 簡單的 dfs 題解:
80分做法還是聽簡單的
對於非樹邊枚舉一下端點狀態
然而我也不知道為什麽就多t了一個點
具體實現上
最暴力的是3^n次 但是我們可以發現對於i不取,j取 i不取,j不取是可以等效成i不取,j沒有限制
CodeForces - 613D:Kingdom and its Cities(虛樹+DP)
for pro void 染色 however == force don tac
Meanwhile, the kingdom of K is getting ready for the marriage of the King‘s daughter. However
HDU-6035:Colorful Tree(虛樹+DP)
node different ase 得到 第一題 false all 直接 files 這裏有三道長得像的題:
一: HDU6036:
There is a tree with nn nodes, eac
[luogu]P4437 [HNOI/AHOI2018]排列
hnoi clas 個數 新的 http 最大 pro spa www 原題鏈接 :P4437 [HNOI/AHOI2018]排列
分析
給定一個序列,第i項有\(a_i,w_i\)兩個屬性。
現在給序列重排列,保持標號不變,要求在新的序列中,第i個數後面不存在第j個數使\
洛谷4103 HEOI2014大工程(虛樹+dp)
題目連結
又是一道虛樹好題啊
我們建出來虛樹,然後考慮dp過程,我們分別令
s
u
m
洛谷3233 HNOI2014(虛樹+dp)
題目連結
膜拜一發
m
t
s
_
「WC2018」通道-邊分治+虛樹+DP
Description
給定三棵樹,最大化
d
i
s
洛谷 P3233 [HNOI2014]世界樹(虛樹+dp)
題面
luogu
題解
資料範圍已經告訴我們是虛樹了,考慮如何在虛樹上面\(dp\)
以下摘自hzwer部落格:
構建虛樹以後兩遍dp處理出虛樹上每個點最近的議事處
然後列舉虛樹上每一條邊,考慮其對兩端點的答案貢獻
可以用倍增二分出分界點
如果a,b的分界點為mid,a,b路徑上a的第一個兒子
BZOJ5287 HNOI2018毒瘤(虛樹+樹形dp)
顯然的做法是暴力列舉非樹邊所連線兩點的選或不選,大力dp。考場上寫的是最暴力的O(3n-mn),成功比大眾分少10分。容斥或者注意到某些列舉是不必要的就能讓底數變成2。但暴力的極限也就到此為止。
每次重新dp做了大量重複的事,考慮從減少重複計算方面優化。先跑一遍沒有限制的樹形dp。將非樹邊所連線的點
[BZOJ5287][Hnoi2018]毒瘤(虛樹 + 樹形 DP)
Address
洛谷 P4426
BZOJ 5287
LOJ #2496
Solution - Step 1
首先我們看到非樹邊最多
11
【CF809E】Surprise me! 樹形DP 虛樹 數學
sum .com body surprise algorithm rac com rap can 題目大意
給你一棵\(n\)個點的樹,每個點有權值\(a_i\),\(a\)為一個排列,求
\[
\frac{1}{n(n-1)}\sum_{i=1}^n\sum_{j=1
luogu P3174 [HAOI2009] 毛毛蟲 樹dp
傳送門
樹形dp基礎題 求帶點權樹直徑
然後這個點權就是每個點的點度(son[])...
所以可以簡化一下
按照正常的套路維護從根開始的最長鏈和次長鏈
dp陣列存的時候+1改成+son[x]-1就可以了
所以dp[x] = maxx + maxxx + son[x] - 1
(maxx 和 ma
luogu P2607 [ZJOI2008] 騎士 樹dp
傳送門
又一個沒有上司的舞會
這個dp有環 媽媽怎麼辦啊
要不...環上隨便斷一條邊?
然後最後選的時候分別取兩個根節點不選的情況的最大值
幾個要點:
1.圖可能是多個環套樹 要迴圈走完
2.不能只記錄頂點 因為如果有重邊的話會把二元環篩掉
3.位運算優先順序..