我們發現對於乙個子樹,若其最少包含的黑色點數為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...