bzoj3573: [Hnoi2014]米特运输
3573: [Hnoi2014]米特运输
Time Limit: 20 Sec Memory Limit: 128 MB
Description
Input
Output
输出文件仅包含一行,一个整数,表示最少的被重建(即修改储存器容量)的米特储存器的数目。
Sample Input
5
4
3
2
1
1 2
1 3
2 4
2 5
Sample Output
HINT
【样例解释】
一个最优解是将A[1]改成8,A[3]改成4,A[5]改成2。这样,2和3运给1的量相等,4和5运给2的量相等,且每天晚上六点的时候,1,2满,3,4,5空,满足所有限制条件。
Source
生平最讨厌的就是题目巨长的题了,实在是难以理解;
首先讲一下题意:就是在一棵树上,每个节点有一个权值val[i],要求修改最少的节点权值(权值可以为实数,不能为负数和0),使得每个val[i]=所有儿子节点的权值和;
如果我们确定了一个节点的权值,那么整个树都可以知道是什么样的了;
然后对于每个节点,如果他儿子有x个,那么他的每个儿子要*x(自己画图试试),这样一来权值可能会很大,但取个对数就可以了;
最后的ans=n-max(一个数出现的次数);
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<cmath> 6 #define MAXN 2000008 7 using namespace std; 8 9 int tmp,ans,n,m,a[MAXN],d[MAXN],tot,head[MAXN],next[MAXN],vet[MAXN]; 10 double son[MAXN],q[MAXN]; 11 12 inline int read(){ 13 char ch=getchar(); int f=1,x=0; 14 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 15 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} 16 return x*f; 17 } 18 19 void add(int x,int y){ 20 tot++; 21 next[tot]=head[x]; 22 head[x]=tot; 23 vet[tot]=y; 24 } 25 26 void dfs(int u,int fa){ 27 for(int i=head[u];i;i=next[i]){ 28 int y=vet[i]; 29 if(y==fa) continue; 30 son[y]=son[u]+log(d[u]); 31 dfs(y,u); 32 } 33 } 34 35 bool cmp(double aa,double bb){ 36 return aa<bb; 37 } 38 39 int main(){ 40 // freopen("1.in","r",stdin); 41 // freopen("1.out","w",stdout); 42 43 n=read(); 44 for(int i=1;i<=n;i++) 45 a[i]=read(); 46 for(int i=1;i<n;i++){ 47 int x,y; 48 x=read(); y=read(); 49 add(x,y); add(y,x); 50 d[x]++; d[y]++; 51 } 52 son[1]=log(1); 53 for(int i=2;i<=n;i++) d[i]--; 54 dfs(1,0); 55 for(int i=1;i<=n;i++) q[i]=log(a[i])+son[i]; 56 sort(q+1,q+n+1,cmp); 57 q[n+1]=-100000000.0; 58 tmp=1; 59 for(int i=2;i<=n+1;i++){ 60 if(fabs(q[i]-q[i-1])<1e-6) tmp++; 61 else ans=max(ans,tmp),tmp=1; 62 } 63 printf("%d",n-ans); 64 }