UPC1430 Color a Tree(貪心)
阿新 • • 發佈:2018-12-13
題意:
一棵樹,n個節點,n-1條邊,每個節點有權值val。Time為當前時間,初始為0,每染一次需要 1s ,對節點 i 染色時要花費 val*Time ,且要對 i 染色要保證 i 的父親節點已被染色。問染完所有節點的最小花費。
思路:
每次找到一個權值最大的節點,如果它是根節點,則首先對它染色。否則,在對它的父親已經染色的情況下,立刻給它染色一定是最優的,所以可以把它和它父親合併為同一個節點,它和它父親的兒子都成為了新節點的兒子,它的父親的父親則是新節點的父親。為了能繼續貪下去,我們給每個節點賦上兩個權值,num_node表示對第i個節點塗色所需的時間(第i個節點實際包含的節點數),sumc表示第i個節點的總權值(第i個節點實際包含的節點的權值和)。此時,我們定義一個節點的權值就等於sumc/num_node。
程式碼:
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5+5; int n, root, ans, fa[maxn], Time[maxn], val[maxn]; void solve(){ for(int i=1; i<n; i++){ double maxnum=0; int maxi; //此處找最大值時可用優先佇列優化 for(int j=1; j<=n; j++){ if(val[j]*1.0/Time[j]>maxnum && j!=root) maxnum=1.0*val[j]/Time[j], maxi=j; } for(int j=1; j<=n; j++) if(fa[j]==maxi) fa[j]=fa[maxi]; ans += Time[fa[maxi]]*val[maxi]; Time[fa[maxi]] += Time[maxi]; val[fa[maxi]] += val[maxi]; val[maxi] = 0; } cout << ans << endl; } int main() { while(cin >> n >> root && (n+root)){ for(int i=1; i<=n; i++){ cin >> val[i]; ans+=val[i], Time[i]=1; } int a, b; for(int i=1; i<n; i++) cin >> a >> b, fa[b]=a; solve(); } }