bzoj5072 小A的樹 樹上揹包

2021-08-10 05:34:41 字數 1401 閱讀 7646

我們發現對於乙個子樹,若其最少包含的黑色點數為a1,最多包含的黑色點數為a2,則在這棵子樹中,能夠包含的黑色點數可以是a1~a2之間的任何數,因為每加入乙個點,黑色點數量最多加1個

我們需要求出對於每個詢問結點量x,其最多和最少包含的黑色結點數,如果詢問的黑色節點數屬於這個區間,則滿足

需要在樹上做揹包,設f[i][j]為以i為根的子樹中選出j個點所能包含的最多黑色結點數,g[i][j]為以i為根的子樹中選出j個點所能包含的最少黑色結點數

轉移則是在某一棵子樹遍歷完後,先不將這棵子樹的所有結點算到根上,而是分為兩部分:1.這棵子樹,2.根和其他子樹(「其他子樹」已經在「這棵子樹」之前被遍歷),這樣我們可以列舉1部分和2部分各自選了j個點和k個點,然後去更新大小為j+k的揹包

#include 

#include

#include

#include

using

namespace

std;

#define debug(x) cerr << #x << "=" << x << endl;

const

int maxn = 5010;

const

int maxm = 5010*2 - 2;

int n,q,vis[maxn],son[maxn],f[maxn][maxn],b[maxn],last[maxn],tot,t,g[maxn][maxn];

int ansf[maxn], ansg[maxn];

bool ***;

struct edge

edge(int u, int v, int to) : u(u), v(v), to(to) {}

}e[maxm];

inline

void add(int u, int v)

inline

void read(int &x)

void dfs(int x)

}son[x] += son[v];//這句放到後面,因為我們把x的一棵子樹和x的其他子樹分離了

}for(int i=1; i<=son[x]; i++)

}void query(int x ,int y) else

}int main()

for(int i=1; i<=n; i++)

memset(f,0,sizeof(f));

memset(g,0x3f,sizeof(g));

memset(ansf,0,sizeof(ansf));

memset(ansg,0x3f,sizeof(ansg));

dfs(1);

for(int i=1; i<=q; i++)

printf("\n");

}return

0;}

bzoj 4317 Atm的樹 樹分治

一道比較經典的樹分治把。二分答案,然後在按照點分治後得到的重心樹中找距離 d的點的數量即可。時間複雜度o nlog 3n ac 如下 include include include include define inf 1000000000 define n 30005 define m 12000...

小機房的樹

題目描述 小機房有棵樹,樹上有n個節點,節點標號為0到n 1,有兩隻蟲子分居在兩個不同的節點上。有一天,他們想爬到乙個節點上去,但是他們不想花費太多精力。已知從某個節點爬到其父親節點要花費c的能量 從父親節點爬到此節點也相同 他們想找出一條花費精力最短的路,要求你告訴他們最少需要花費多少精力。輸入描...

bzoj 世界樹 虛樹 樹形DP lca

include include include include include define inf 0x3f3f3f3f define rep0 i,n for int i 0 i n i define rep1 i,n for int i 1 i n i define rep 0 i,n for...