UVA - 1205 Color a Tree

Posted 蒟蒻JHY

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVA - 1205 Color a Tree相关的知识,希望对你有一定的参考价值。

 

 

     大意就是给你一颗树,每个点有一个权值w[i],求一个排列使得 所有的父亲都在儿子前面 并且排列的权值最小。

    排列的权值在这里定义为 Σ i * w[p[i]]   ,其中p[i] 是排列第i个位置的元素。

 

    然后我瞎jb胡了一个算法,对于每个子树维护一个 p[],表示只考虑子树内的元素的最优排列。显然我们只要把一个点的所有儿子都合并之后再把这个点放在排列的第一个位置就可以了。(可以证明这些元素再往上走的时候相对位置还是一样的)

    问题是怎么合并。

    其实这就是个dp,合并x和y子树的时候,f[i][j] 表示 用了x子树前i个元素,用了y子树前j个元素,此时到终点的最优值是多少,然后顺带记录一下方案就好啦。

 

    (昨天+今天调了 3h+  主要是因为 fill 用了 0x7f  一直没有察觉233333,导致max一直是127(真是醉了))

 

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1005;
int a[maxn][maxn],n,w[maxn],f[maxn][maxn];
int to[maxn*2],ne[maxn*2],hd[maxn],num,m;
bool nxt[maxn][maxn];
inline void add(int x,int y){ to[++num]=y,ne[num]=hd[x],hd[x]=num;}

inline void init(){
	memset(hd,0,sizeof(hd)),num=0;
	memset(f,0x7f,sizeof(f));
	memset(a,0,sizeof(a));
}

inline void Merge(int x,int son){
	int b[a[x][0]+a[son][0]+5],hzx[a[x][0]+5],hzs[a[son][0]+5];
    hzx[a[x][0]+1]=0;
    for(int i=a[x][0];i;i--) hzx[i]=hzx[i+1]+a[x][i];
    hzs[a[son][0]+1]=0;
    for(int i=a[son][0];i;i--) hzs[i]=hzs[i+1]+a[son][i];
    
    f[a[x][0]][a[son][0]]=0;
    for(int i=a[x][0];i>=0;i--)
        for(int j=a[son][0];j>=0;j--){
        	if(i<a[x][0]&&f[i+1][j]<f[i][j]) f[i][j]=f[i+1][j],nxt[i][j]=1;
        	if(j<a[son][0]&&f[i][j+1]<f[i][j]) f[i][j]=f[i][j+1],nxt[i][j]=0;
        	f[i][j]+=hzx[i+1]+hzs[j+1];
		}
	
	int now=0,nx=0,ny=0;
	while(++now<=a[x][0]+a[son][0]){
		if(nxt[nx][ny]) nx++,b[now]=a[x][nx];
		else ny++,b[now]=a[son][ny];
    }
	
	for(int i=0;i<=a[x][0];i++) fill(f[i],f[i]+a[son][0]+1,2000000000);
	a[x][0]+=a[son][0];
	for(int i=1;i<=a[x][0];i++) a[x][i]=b[i];
}

void dfs(int x,int fa){
	for(int i=hd[x];i;i=ne[i]) if(to[i]!=fa){
		dfs(to[i],x);
		Merge(x,to[i]);
	}
	
	a[x][0]++;
	for(int i=a[x][0];i>1;i--) a[x][i]=a[x][i-1];
	a[x][1]=w[x];
}

inline void calc(int x){
	int ans=0;
	for(int i=1;i<=n;i++) ans+=i*a[x][i];
	printf("%d\\n",ans);
}

int main(){
	int uu,vv,root;
	while(scanf("%d%d",&n,&root)==2&&n&&root){
		init();
	    for(int i=1;i<=n;i++) scanf("%d",w+i);
	    for(int i=1;i<n;i++) scanf("%d%d",&uu,&vv),add(uu,vv),add(vv,uu);
	    dfs(root,-1),calc(root);
	}
	return 0;
}

  

以上是关于UVA - 1205 Color a Tree的主要内容,如果未能解决你的问题,请参考以下文章

UVA152 Tree's a Crowd暴力+最值

UVa 536 Tree Recovery | GOJ 1077 Post-order (习题 6-3)

UVa 615 - Is It A Tree?

[模拟退火][UVA10228] A Star not a Tree?

UVA - 1625 Color Length

UVA - 12424 Answering Queries on a Tree(十棵线段树的树链剖分)