有
n n
名候選人,從
1' role="presentation">11到
n n
編號,有乙個隊長的編號為
0' role="presentation">0
0,每個候選人都由一位編號比他小的候選人推薦(如果為
0 0
則表示是隊長推薦的)。隊長希望招募
k' role="presentation">k
k個人,但是他需要保證:如果招募了
x x
,那麼他的推薦人也要招募(隊長總是在團隊裡的)。每個人都有代價 ci
' role="presentation">cic
i和價值 wi
w
i兩個值,招募可以獲得的價值為 an
swer
=∑wi
∑ci ans
wer=
∑wi∑
ci
,你需要最大化這個值,答案保留
3 3
位小數。1⩽
k⩽n⩽
2500
' role="presentation">1⩽k
⩽n⩽25001⩽
k⩽n⩽
2500,1
⩽ci,
wi⩽10
4 1⩽c
i,wi
⩽10
4先做乙個小轉化:以
0 0
為根節點,選擇 k+
1' role="presentation">k+1
k+1個點,其中根節點必須選擇。
首先我們考慮樹形
dp dp
,顯然是一道普通的樹上揹包問題。但是由於答案是乙個比值,無法記錄狀態進行轉移,所以我們引入
01 01
分數規劃。
這個式子顯然是可以二分答案的,因此可以得到 ∑w
i∑ci
⩾x∑ wi
∑ci⩾
x由於分母是正數,我們將式子拆開 ∑w
i⩾x×
∑ci⟹
∑wi⩾
∑x×c
i ∑wi
⩾x×∑
ci⟹∑
wi⩾∑
x×ci
可得 ∑w
i−x×
ci⩾0
∑ wi
−x×c
i⩾
0故我們可以二分答案
x x
,將問題轉化為:每個點有
1' role="presentation">1
1個屬性 pi
=wi−
x×ci
p i=
wi−x
×c
i,能否使選取的
k k
個點的屬性和大於等於
0' role="presentation">00。
設計狀態:f[
i][j
] f[i
][j]
表示在以第
i i
個節點為根的子樹中,選擇
j' role="presentation">j
j個節點的最大屬性和。
dp dp
為樸素的樹上揹包問題,轉移非常顯然(注意根節點
i i
對應的
j' role="presentation">j
j至少為
1 1
,我就因為這個除錯了半天)。
注意初始化:f[
i][0
]=0' role="presentation">f[i
][0]
=0f[
i][0
]=0,
f[i]
[1]=
wi−x
×ci f[i
][1]
=wi−
x×ci
,其餘狀態的值均為無窮小。
時間複雜度:θ(
n2) θ(n
2)
(複雜度證明見 「haoi 2015」樹上染色)
#include
#include
#include
using
namespace
std;
const
int n=2505;
const
double eps=1e-5;
int n,m,tot,c[n],s[n],hd[n],sz[n];
double w[n],f[n][n];
struct edgee[n];
void add(int u,int v)
void dfs(int x)
}bool check(double x)
int main()
double l=0,r=1e4,ans=0;
while(l+eps<=r)
printf("%.3lf\n",ans);
return
0;}
JSOI2016 最佳團體
題面 給定一棵樹,每個點有代價和價值,現在求乙個點集,使得點集中每個點的祖先也都在點集中,且點集中所有點的價值和 代價和最大。題解價值和 代價和最大 過於明顯的01分數規劃,直接把a mid j作為點權跑樹形dp,然後看f r oot 1 f root 1 f root 1 是否大於0即可。據說這題...
JSOI2016 最佳團體
嘟嘟嘟 01分數規劃 樹形揹包。然後就沒了。結果我調了半天,原因還是樹形揹包不熟練。我是用dfs序求的,轉化的時候,是dp i j 轉化到dp i 1 j 1 或dp i siz pos i j 而不是像普通的dp從別的狀態轉化到dp i j 所以最後的答案應該考慮到dp n 1 m 1 而不是只到...
JSOI2016 最佳團體
jsoi資訊學代表隊一共有n名候選人,這些候選人從1到n編號 方便起見,jyy的編號是0號。每個候選人都由一位編號比他小的候選人ri推薦 如果ri 0 則說明這個候選人是jyy自己看上的 為了保證團隊的和諧,jyy 需要保證,如果招募了候選人i,那麼候選人r 也一定需要在團隊中。當然了,jyy自己總...