2054 貪心 並查集

2021-08-29 07:41:40 字數 1532 閱讀 4030

貪心的總體思路是:每次找到乙個權值最大的節點,如果它是根節點,則首先對它染色,

否則的話我們可以得出乙個結論,在對它的父親已經染色的情況下,立刻給它染色是最優的。

現在重點討論第二種情況,當它不是根節點時,我們如果對它父親染了色,則一定會立刻對它染色,

所以可以把它和它父親合併為同乙個節點,它和它父親的兒子都成為了新節點的兒子,它的父親的父親則是新節點的父親。

為了能繼續貪下去,我們給每個節點賦上兩個權值,

num_node表示對第i個節點圖色所需的時間(第i個節點實際包含的節點數),sumc表示第i個節點的總權值(第i個節點實際包含的節點的權值和)。貪心目標是sumc/num_node的原因應該是因為如果想要為乙個節點塗色,必須將一條路線都塗色。

題目樣例分析:

粉刷順序與合併順序是不一樣的,

粉刷順序為: 1,3,5,2,4

合併順序為:

fa          num_node(包含點數) sumc(當前權值) ans(當前花費)

5         3              1                 4                4         他父親(3)加4+4

3         1              2                 5                9         他父親(1)加14=9*1+5

2         1              1                 2                2         他父親(1)加8=3*2+2

4         1              1                 2                2         他父親(1)加10=4*2+2

最後33 = 1 + 14 + 8 + 10

#include#include#include#include#includeusing namespace std;

struct nodenode[1001];

int find(int p)

int main()

node[r].father = r;

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

int index;

double maxv;

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

}node[index].flag=1;

int father = find(index);

node[father].ans += node[index].ans + node[index].sumc*node[father].num_node;

//重要:父親的總花費=孩子總花費+孩子總權值*父親的順序值

node[father].sumc += node[index].sumc;

node[father].num_node += node[index].num_node;

} printf("%d\n", node[r].ans);

}}

導遊 (並查集 貪心)

幫助mr.he找出所有遊客帶到目的地,且往返次數最少的路線,如果不能把遊客送到目的地,輸出 no 輸入格式 第一行兩個整數n和r,分別表示城市數量和道路數量,各城市編號為1.n。接下來的r行,每行3個整數 a b p,表示道路ab的最大載客量為p。最後有若干行,每包含3個整數 s d t,分別表示出...

Supermarket(貪心 並查集)

題目鏈結 原創的部落格 題意 超市裡有n個商品.第i個商品必須在保質期 第di天 之前賣掉,若賣掉可讓超市獲得pi的利潤。每天只能賣乙個商品。現在你要讓超市獲得最大的利潤。n p i d i 範圍都在10000以內 include include include include include in...

並查集 bzoj2054 瘋狂的饅頭

因為只有最後被染上的顏色會造成影響,所以倒著處理,用並查集維護已經染色的區間的右端點,即fa i 為i所在的已染色區間的右端點,這樣可以保證o n 的複雜度。include includeusing namespace std define n 1000001 inline void p int x...