1. 程式人生 > >[BZOJ5287][Hnoi2018]毒瘤(虛樹 + 樹形 DP)

[BZOJ5287][Hnoi2018]毒瘤(虛樹 + 樹形 DP)

Address

Solution - Step 1

  • 首先我們看到非樹邊最多 11 11
  • 很容易想到暴力列舉每條非樹邊的兩個端點是否在獨立集內
  • 然後樹上 DP 求獨立集個數
  • 複雜度 O
    ( 3 m n × n )
    O(3^{m-n}\times n)
  • 然後我們發現對於一條非樹邊 ( u , v ) (u,v)
    ,如果強制 u u 不在獨立集內,那麼 v v 點沒有再去強制的必要
  • 所以只需要列舉 2 2 種情況
  • (1) u u 在獨立集內, v v 不在獨立集內
  • (2) u u 不在獨立集內
  • 複雜度 O ( 2 m n × n ) O(2^{m-n}\times n)
  • 常數優秀的程式能夠水過

Solution - Step 2

  • 考慮把 DP 的複雜度優化掉
  • 發現這個 DP 與對整棵樹進行 DP 的區別僅僅是強制了 O ( m n ) O(m-n) 個點選或不選
  • 考慮虛樹
  • 把所有非樹邊的端點放在一起建立虛樹
  • 注意:為了消除虛樹根的子樹之外點的影響,需要把整棵樹的根節點加入關鍵點集合
  • 然後在虛樹上 DP ,轉移方程為
  • f [ u ] [ 0 ] = h [ u ] [ 0 ] × v s o n [ u ] ( f [ v ] [ 0 ] × g [ ( u , v ) ] [ 0 ] [ 0 ] + f [ v ] [ 1 ] × g [ ( u , v ) ] [ 0 ] [ 1 ] ] ) f[u][0]=h[u][0]\times\prod_{v\in son[u]}(f[v][0]\times g[(u,v)][0][0]+f[v][1]\times g[(u,v)][0][1]])
  • f [ u ] [ 1 ] = h [ u ] [ 1 ] × v s o n [ u ] ( f [ v ] [ 0 ] × g [ ( u , v ) ] [ 1 ] [ 0 ] + f [ v ] [ 1 ] × g [ ( u , v ) ] [ 1 ] [ 1 ] ) f[u][1]=h[u][1]\times\prod_{v\in son[u]}(f[v][0]\times g[(u,v)][1][0]+f[v][1]\times g[(u,v)][1][1])
  • f [ u ] [ 0 ] f[u][0] 虛樹上 u u 的子樹內不選 u u 的獨立集個數
  • f [ u ] [ 1 ] f[u][1] 虛樹上 u u 的子樹內不選 u u 的獨立集個數
  • s o n [ u ] son[u] 虛樹上 u u 的子節點集合
  • g [ ( u , v ) ] [ x ] [ y ] g[(u,v)][x][y] 原樹上 u u v v 的路徑(虛樹上 u u v v 的父親節點), u u 的選擇狀態為 x x v v 的選擇狀態為 y y ,設原樹上 w w u u 的子節點且是 v v 的祖先,就 w w 的子樹內但不在 v v 的子樹內的所有點與 u u v v 構成獨立集的方案數,畫個圖長這樣
    在這裡插入圖片描述
  • 即為強制 u u 的狀態為 x x v v 的狀態為 y y 時,黃色部分構成獨立集的方案數
  • h [ u ] [ 0 / 1 ] h[u][0/1] 表示 u u 的子樹內,除去所有 v v 的子樹( v v 滿足其子樹記憶體在虛樹點), u u 不選 / 選的方案數
    在這裡插入圖片描述
  • 如上圖,紫色點為虛樹點,特殊地, u u 為虛樹點
  • g g 可以建出虛樹之後大力預處理, h h 可以在樹上 DP 求出
  • 這樣我們就能 O ( m n ) O(m-n) 實現 DP 了
  • 複雜度 O ( n log n + 2 m n × ( m n ) ) O(n\log n+2^{m-n}\times(m-n))

Code

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define Edge(u) for (int e = adj[u], v = go[e]; e; e = nxt[e], v = go[e])
#define Tree(u) for (int e = adj[u], v; e; e = nxt[e]) if ((v = go[e]) != fu)
#define Vir(u) for (int e = adj2[u], v = go2[e]; e; e = nxt2[e], v = go2[e])

inline int read()
{
	int res = 0; bool bo = 0; char c;
	while (((c = getchar()) < '0' || c > '9') && c != '-');
	if (c == '-') bo = 1; else res = c - 48;
	while ((c = getchar()) >= '0' && c <= '9')
		res = (res << 3) + (res << 1) + (c - 48);
	return bo ? ~res + 1 : res;
}

template <class T>
inline void Swap(T &a, T &b) {a ^= b; b ^= a; a ^= b;}

const int N = 1e5 + 5, M = 2e5 + 100, LogN = 20, ZZQ = 998244353;

int n, m, ecnt, nxt[M], adj[N], go[M], tot, U[N], V[N], FA[N],
virn, vir[N], T, dfn[N], fa[N][LogN], dep[N], stk[N], top, virfa[N],
f[N][2], val[N][2][2], col[N], ans, ecnt2, nxt2[N], adj2[N], go2[N],
fh[N][2], exc[N][2], tt, uv[N];
bool vis[N];

void add_edge(int u, 
            
           

相關推薦

BZOJ5287 HNOI2018毒瘤+樹形dp

  顯然的做法是暴力列舉非樹邊所連線兩點的選或不選,大力dp。考場上寫的是最暴力的O(3n-mn),成功比大眾分少10分。容斥或者注意到某些列舉是不必要的就能讓底數變成2。但暴力的極限也就到此為止。   每次重新dp做了大量重複的事,考慮從減少重複計算方面優化。先跑一遍沒有限制的樹形dp。將非樹邊所連線的點

[BZOJ5287][Hnoi2018]毒瘤 + 樹形 DP

Address 洛谷 P4426 BZOJ 5287 LOJ #2496 Solution - Step 1 首先我們看到非樹邊最多 11

2018.09.25 bzoj2286: [Sdoi2011]消耗戰+樹形dp

傳送門 又一道虛樹入門題。 這個dp更簡單啊。 直接記錄每個點到1的距離,簡單轉移就行了。 程式碼: #include<bits/stdc++.h> #define N 250005 #de

Codeforces 1111 E. TreeDP

cto cond using push end %d inf ces tree 題意 有一棵樹,q個詢問,每次詢問,指定一個點做樹根,再給定k個點,要求把這些點分成不超過m組的方案數,分配的限制是任意兩個有祖先關系的點不能分在同一組。題目還保證了所有的詢問的k加起來不超過

騎士 HYSBZ - 1040基環+樹形dp

inpu c++ desc 匯聚 signed long ons clu inf  Z國的騎士團是一個很有勢力的組織,幫會中匯聚了來自各地的精英。他們劫富濟貧,懲惡揚善,受到社會各界的贊揚。最近發生了一件可怕的事情,邪惡的Y國發動了一場針對Z國的侵略戰爭。戰火綿延五百裏,

[LOJ#2587][APIO2018]鐵人兩項圓方+樹形dp

Address 洛谷P4630 LOJ#2587 Solution 繼 APIO 2018 之後,圓方樹重出江湖! 圓方樹大概就是,將圖的每個點雙連通分量建一個方點,把連通分量裡的點全部連向這個方點,形成一棵樹。原圖中的點為圓點。 圓方樹能處理與圖連通性有關的許多問題。 回到原問

洛谷2607 騎士基環+樹形DP

傳送門 【題目分析】 第一眼:咦這不簡單樹形DP嗎? 第二眼:嗯?這不是有N條邊嗎?怎麼就樹形DP了? 第三眼:唉好像拆一條邊不就N-1條邊了嗎?哎嘿嘿我太聰明瞭。。。。 噼裡啪啦打完一交,WA完。。。。。。。一臉懵???才發現可能直接將整個圖(以為保證連通)拆成兩個聯通塊了。。

洛谷3233 BZOJ3572 HNOI2014 世界 樹形dp

題目連結 題意: 給你一棵n個點的樹,邊的邊權都是1,有m次詢問,每次選出若干個點,對於每次詢問,每個點要劃分給離它最近的被選出來的點,如果有多個距離相同的點,則把這個點劃分給這幾個距離相同的點中編號最小的點,求每次詢問選出的這些點各自分得了多少個點。

洛谷2495 BZOJ2286 SDOI2011 消耗戰 樹形dp

題目連結 題意: 給你一棵以1為根的樹,邊有邊權,有m次詢問,每次詢問選出k個點,問這k個與1號點都不連通要割斷的最小邊權和。 n ,

Hard F2. Representative Sampling +樹形DP

Description 給你n個字串,讓你選出k個字串使它們的價值最大,定義一個集合的價值為兩兩最長公共字首和。 Sample Input 3 2 aba bzd abq Sample Output 2 你可以先建出一個字典樹,建出一個虛樹。 然後節點不會

BZOJ5341[Ctsc2018]暴力寫掛——邊分治++樹形DP

題目連結: CSTC2018暴力寫掛   題目大意:給出n個點結構不同的兩棵樹,邊有邊權(有負權邊及0邊),要求找到一個點對(a,b)滿足dep(a)+dep(b)-dep(lca)-dep'(lca)最大,其中dep為第一棵樹中的深度,dep'為第二棵樹中的深度,lca為兩點的最近公共祖先。

bzoj 1040: [ZJOI2008]騎士 環套+樹形dp

1040: [ZJOI2008]騎士 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3719  Solved: 1403 [Submit][Status][Discuss] Description   Z國的騎士團是一

bzoj3611: [Heoi2014]大工程 +樹形dp

題目大意:給定一棵樹,m次詢問,每次給出k個關鍵點,詢問這k個點之間的兩兩距離和、最小距離和最大距離 n<=100W,m<=50000,Σk<=2*n 思路:利用LCA單調性,每次詢問的時候重新建樹,在這棵樹上做DP,使得總體時間複雜度降到

P2495 [SDOI2011]消耗戰 lca倍增++樹形dp

img const 二進制 圖片 樹形 struct 父節點 scan add 題目:給出n個點的樹 q次詢問 問切斷 k個點(不和1號點聯通)的最小代價是多少 思路:樹形dp sum[i]表示切斷i的子樹中需要切斷的點的最小代價是多少 mi[i]表示1--i中的最

降臨線段優化dp

main spa space odi pri line 除了 發現 獲得 降臨 選定點i會有代價\(c_i\),如果一個區間j內的點全被選擇,就可以獲得回報\(p_j\)。點數和區間個數\(<1e5\)。 還以為是線段樹優化網絡流(50萬個點200萬條邊看上去很可

hdu 1520 Anniversary party第一道樹形dp

include 描述 pro ace rsa input mes red contain 傳送門: http://acm.hdu.edu.cn/showproblem.php?pid=1520 Anniversary party Time Limit: 2000/1000

題解:CF115E線段優化dp

定義 可能 bit tput space nbsp sans odi bsp 題目描述 你是一個賽車比賽的組織者,想在線性王國中安排一些比賽。 線性王國有n條連續的從左到右的道路。道路從左到右依次編號為從1到n,因此道路按照升序排列。在這些道路上可能會有幾場比賽,每一場

CF-833B The Bakery線段優化Dp

imu ger another art 區間 produce let span start Some time ago Slastyona the Sweetmaid decided to open her own bakery! She bought r

[BZOJ4753][Jsoi2016]最佳團體分數規劃+樹形DP

Address 洛谷P4322 BZOJ4753 LOJ#2071 Solution 看到最大化分式的值,考慮分數規劃,二分答案 m i

CTSC1998 選課揹包類樹形Dp

題意: 給出 n 節課的先修課號以及學分(先修課號指的是在學習某節課時先需要學習的課程),求學 m 節課的最大學分。 細節: 1、對於課程 a 其先修課號為 b ,對於課程 b 其先修課號為 c ,則需要學 a 的方式必須為先學 c 在學 b。 2、可能存在多門課程沒有先修課號。