acdream 1031 Component(树中一个大小为k的节点集最小权值)
2012-11-23 13:55
253 查看
题目链接: http://www.acdream.net/problem.php?id=1031
题意:给出一棵n个节点的树,输出n个数,第i个数表示树中一个大小为i的连通分量最小的权值。(每个节点有一个权值)
思路:分治+DP。。。这个DP好巧妙。。。f[i][j]表示以当前节点new_root为根的树中DFS形成的遍历序列(这整个序列大小为m)后m-i+1个节点中选出一个大小为j的集合的最小权值。
题意:给出一棵n个节点的树,输出n个数,第i个数表示树中一个大小为i的连通分量最小的权值。(每个节点有一个权值)
思路:分治+DP。。。这个DP好巧妙。。。f[i][j]表示以当前节点new_root为根的树中DFS形成的遍历序列(这整个序列大小为m)后m-i+1个节点中选出一个大小为j的集合的最小权值。
#include <iostream> #include <cstdio> #include <vector> #include <string.h> #define min(x,y) ((x)<(y)?(x):(y)) #define max(x,y) ((x)>(y)?(x):(y)) using namespace std; const int INF=2000000000; const int MAX=2005; vector<int> V[MAX],node; int n,ans[MAX],visit[MAX],f[MAX][MAX],w[MAX]; int size[MAX],max_subtree[MAX]; void DFS(int u,int pre) { size[u]=1; max_subtree[u]=0; node.push_back(u); int i,v; for(i=0;i<V[u].size();i++) { v=V[u][i]; if(v==pre||visit[v]) continue; DFS(v,u); size[u]+=size[v]; max_subtree[u]=max(max_subtree[u],size[v]); } } void divide(int root) { node.clear(); DFS(root,-1); int new_root,temp=INF,i,j,k,v,tot=node.size(); for(i=0;i<tot;i++) { v=node[i]; k=max(tot-size[v],max_subtree[v]); if(k<temp) temp=k,new_root=v; } node.clear(); DFS(new_root,-1); tot=node.size(); f[tot][0]=0; for(i=1;i<=tot;i++) f[tot][i]=INF; for(i=tot-1;i>=0;i--) { v=node[i]; for(j=0;j<=tot;j++) { f[i][j]=f[i+size[v]][j]; if(j) f[i][j]=min(f[i][j],f[i+1][j-1]+w[v]); } } for(i=1;i<=tot;i++) ans[i]=min(ans[i],f[1][i-1]+w[new_root]); visit[new_root]=1; for(i=0;i<V[new_root].size();i++) { v=V[new_root][i]; if(!visit[v]) divide(v); } } int main() { while(scanf("%d",&n)!=-1) { int i,j,u,v; for(i=1;i<=n;i++) scanf("%d",w+i),V[i].clear(); for(i=1;i<n;i++) { scanf("%d%d",&u,&v); V[u].push_back(v); V[v].push_back(u); } memset(visit,0,sizeof(visit)); for(i=1;i<=n;i++) ans[i]=INF; divide(1); for(i=1;i<n;i++) printf("%d ",ans[i]); printf("%d\n",ans[i]); } return 0; }
相关文章推荐
- 【codeforces 721D】【贪心 堆】D. Maxim and Array 【给出n个数,k次机会,每次使得任意一个数字减少或者加上x,使得最后的乘积最小,最后的n个数大小】
- 牛牛和15朋友来玩打土豪分田地的游戏,牛牛决定让你来分田地,地主的田地可以看成是一个矩形,每个位置有一个价值。分割田地的方法是横竖各切三刀,分成26份,作为领导干部,牛牛总是会选择其中总价值最小的一份田地,作为牛牛最好的朋友,你希望牛牛取得的田地价值和尽可能大,你知道这个值最大可以是多少吗? 输入两个整数n和m(1≤n,m≤75)表示田地的大小,接下来n行,每行包括m个0-9之间的数字,表示每块
- 给定一颗二叉树,以及其中的两个node(地址均非空),要求给出这两个node的一个公共父节点,使得这个父节点与两个节点的路径之和最小。
- hdu 5678 ztr loves trees (给一颗有根树,树上的每一个节点有一个权值,每次询问某个子树中所有权值的中位数)
- hdu 2121无根最小树形图要建一个虚拟节点
- 二叉树中权值最大的叶节点到权值最小的叶节点的距离
- NYOJ 925 最小生成树(按权值大小排序生成树)+查重函数unique
- hdu 2121无根最小树形图要建一个虚拟节点
- 面试算法——权值最大的叶节点到权值最小的叶节点的距离
- ACdream 1135(MST-最小生成树边上2个值,维护第一个最小的前提下让还有一个最小)
- 数据结构:设有一个不带头结点的单链表L,设计两个递归算法,del(L,x)删除单链表L中第一个值为x的节点,delall(L,x)删除单链表L中的最小节点值。
- 100亿个无序数,给定里面其中一个数A,找出与A大小相差最小的各10个数
- 以线框的方式画一个节点的最小BoundingBox
- 二叉树权值最大的叶子节点到权值最小的叶子节点的距离
- POJ 1125 Stockbroker Grapevine floyd多源最短路,选取一个点,使最大边的权值是最小的
- uva11090 给你一个有向图,求出平均权值最小的环
- Python 技巧(二) 最小堆实现以及维护一个大小为100的最小堆
- 5-7 删除一个节点:步骤1-删除最大值,最小值
- 一个图的两棵最小生成树,边的权值序列排序后结果相同
- 一个弹出层,相对浏览器居中,可以随浏览器缩放大小,有最大值和最小值(当然不支持ie6)