題目
天色已暗,女牧羊人需要把她的羊群聚集到一起。
女牧羊人牧羊的地方有 \(n\) 塊大草坪,它們由 \(n-1\) 條道路連線,保證草坪之間兩兩聯通。女牧羊人有兩種羊:普通的羊和領頭羊。最開始,每塊草坪上都有且僅有乙隻領頭羊和乙隻普通羊。女牧羊人每次可以選擇兩塊相鄰的草坪 \(x\) 和 \(y\),並進行以下兩種操作中的任意乙個:
此外,每種操作也是需要花費時間的:遷移 乙隻 領頭羊一次的時間為 \(a\),遷移 乙隻 普通羊一次的時間為 \(b\)(一次是指從一塊草坪到另乙個相鄰的草坪)。女牧羊人需要在盡可能少的時間內把所有的羊遷移到同一塊草坪上。你能幫幫她嗎?
題目鏈結
題解首先要理解題意,找出一般做法,我們結合樣例進行理解。
樣例輸入:
6 2 31 44 2
4 62 3
2 5樣例輸出:
對於該樣例,如果我們選用點1為根結點,將所有羊移動到根結點,所需的費用是85,如果我們選用4為根結點,所需的費用是65,我們看看當選4為根結點時費用是如何計算出來的。
首先,我們可以將所有普通羊集中到點1(其實點6也可以)所需費用為\(b*(1+1+3+1+5)\),然後將所有除1之外的領頭羊集中到點4,所需費用為\(a*(1+1+3+1)\),最後將1結點的所有羊移動到4結點,所需費用為\(a*1+b*6\)。
仔細分析,我們可以得出一般操作策略,即如果將羊集中到點u,那麼我們需要先將所有普通羊集中到點u的兒子v,然後將所有領頭羊集中到點u(除v點的領頭羊),最後進行一次操作二,將所有v點的羊集中到u點。可以證明,當v為葉子結點時,所需費用最優。
設size[u]表示以u為根的子樹中結點的數量,設\(sum[u]=\sum_size[v]\),簡單理解就是u子樹的結點移動到u的單位費用和。設u為根,v為u的乙個葉子兒子,考慮兩種情況:
1、移動所有領頭羊到點u,其代價為\(a*(sum[u]-size[u])\),減去\(size[u]\)是因為移動到u之後就不用再移動了,因為u為根結點,所以\(size[u]=n\)。
2、移動所有普通羊到點v,再將所有普通羊從點v移動到u,所有普通羊移動到點v的代價為\(b*(sum[u]-size[v]-size[v])\),然後將所有普通羊從點v移動到根u的代價為\(b*n\),當v為葉子結點時,\(size[v]=1\),所以總代價為\(b*(sum[u]-2+n)\)。
綜合考慮以上兩種情況,將所有羊移動到根u的代價為\(a*(sum[u]-n)+b*(sum[u]-2+n)\),由公式看出,這個代價只和sum[u]有關。
如果我們需要將根u換為跟根v,則我們需要更新sum[v],即以v為根所有點移動到v的代價。容易得到\(sum[v]=sum[u]-size[v]-size[v]+n\)。更新了sum[v],即可以更新以v為根的最小費用。
**
#includeusing namespace std;
const int n=2*1e5+5;
int n,a,b,x,y;
long long size[n],sum[n],ans=1e18;
vectorg[n];
void dfs(int u,int fa)
sum[u]+=size[u];
}void change_root(int u,int fa)
}int main()
dfs(1,-1);
change_root(1,-1);
printf("%lld",ans);
}
oiclass1454 選課 樹上揹包
題目 在大學裡每個學生,為了達到一定的學分,必須從很多課程裡選擇一些課程來學習,在課程裡有些課程必須在某些課程之前學習,如高等數學總是在其它課程之前學習。現在有 n 門功課,每門課有個學分,每門課有一門或沒有直接先修課 若課程 a 是課程 b 的先修課即只有學完了課程 a 才能學習課程 b 乙個學生...
oiclass4094 騎士 基環樹
問題描述 z 國的騎士團是乙個很有勢力的組織,幫會中匯聚了來自各地的精英。他們劫富濟貧,懲惡揚善,受到社會各界的讚揚。最近發生了一件可怕的事情,的 y 國發動了一場針對 z 國的侵略戰爭。戰火綿延五百里,在和平環境中安逸了數百年的 z 國又怎能抵擋的住 y 國的軍隊。於是人們把所有的希望都寄託在了騎...
oiclass3904 種樹 樹形DP 換根
題目 題面bluesky007喜歡種樹。一天,她得到了一棵 n 個點的樹,其中節點 i 重量為 w i 在種樹之前,bluesky007需要用起重機把樹吊起。由於她只有一台起重機,所以她只能選擇乙個點作為受力點。根據bluesky007所在世界的物理知識,吊起一棵樹需要做的功為 sum w i cd...