BZOJ3573 [Hnoi2014]米特運輸 【貪心】
阿新 • • 發佈:2018-05-21
保留 clas pan size cst () log getch sin
題目鏈接
BZOJ3573
題解
題目又臭又長系列
題意:修改盡量少的點權,使得:
①同個節點的所有兒子點權相同
②任意非葉節點權值等於其兒子權值之和
容易發現一旦任意一個點權值確定,整棵樹權值就確定
一個比較簡單的想法是枚舉根節點權值
但我們可以通過計算出每個節點如若保留原值,根節點會是什麽值
如果兩個節點能同時不變,當且僅當它們對應根節點權值相等
我們算出來排序選擇權值最多的那一個就好了
直接乘會爆\(long long\),可使用\(log\)轉化為加法
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
#define eps 1e-9
using namespace std;
const int maxn = 500005,maxm = 1000005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == ‘-‘) flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1 ) + c - 48; c = getchar();}
return out * flag;
}
int tot;
double H[maxn];
int n,val[maxn],de[maxn];
int h[maxn],ne = 1;
struct EDGE{int to,nxt;}ed[maxm];
inline void build(int u,int v){
ed[++ne] = (EDGE){v,h[u]}; h[u] = ne;
ed[++ne] = (EDGE){u,h[v]}; h[v] = ne;
de[u]++; de[v]++;
}
double v[maxn];
int fa[maxn];
void dfs(int u){
if (u == 1) v[u] = log(1);
else v[u] = v[fa[u]] + log(fa[u] == 1 ? de[fa[u]] : de[fa[u]] - 1);
H[++tot] = v[u] + log(val[u]);
Redge(u) if ((to = ed[k].to) != fa[u]){
fa[to] = u; dfs(to);
}
}
int main(){
n = read();
REP(i,n) val[i] = read();
for (int i = 1; i < n; i++) build(read(),read());
dfs(1);
int ans = 0,cnt = 0;
sort(H + 1,H + 1 + tot);
for (int i = 1; i <= tot; i++){
if (fabs(H[i] - H[i - 1]) > eps) ans = max(ans,cnt),cnt = 1;
else cnt++;
}
ans = max(ans,cnt);
printf("%d\n",n - ans);
return 0;
}
BZOJ3573 [Hnoi2014]米特運輸 【貪心】