随笔 - 58,  文章 - 0,  评论 - 4,  阅读 - 3251

一、题目描述:

  给你一颗 n 个节点的有根树。节点 i 的价值为 vi,费用为 wi

  你需要选择 k 个节点,使得 i=1nvii=1nwi 最大。

  约束:选择一个节点之前,必须先选择它的父亲节点。(根节点除外)

  输出 i=1nvii=1nwi 的最大值。答案精确到三位小数。

  数据范围 1kn25001vi,wi1×104


 二、解题思路:

  是我以前从未见过的分数规划题目。

  分数规划题的形式就是让你求 i=1kvii=1kwi 的最值。

  其实写了一道题就不难了,个人觉得比较套路。一般我们二分求解分数规划。过程如下:

   mid 

   mid 使 i=1kvii=1kwi>=mid 

   i=1k(vimid×wi)>=0 

   x  g(x)=vxmid×wx 

   k  g(x),0 

  于是就是比较板的树形背包题了,时间复杂度 O(nk×log21e8)


 三、完整代码:

复制代码
 1 #include<iostream>
 2 #include<iomanip>
 3 #include<algorithm>
 4 #define N 3010
 5 #define ll long long
 6 #define rep(i,l,r) for(int i=l;i<=r;i++)
 7 #define per(i,r,l) for(int i=r;i>=l;i--)
 8 #define tep(i,u) for(int i=head[u];i!=-1;i=e[i].nxt)
 9 using namespace std;
10 int n,m,s[N];
11 double g[N],v[N],w[N],f[N][N];
12 struct EDGE{
13     int v,nxt;
14 }e[N*2];
15 int head[N],cnt;
16 void add(int u,int v){
17     e[++cnt].v=v;
18     e[cnt].nxt=head[u];
19     head[u]=cnt;
20 }
21 void Max(double &a,double b){a=max(a,b);}
22 void solve(int u,int ff){
23     tep(i,u){
24         if(e[i].v==ff) continue;
25         int to=e[i].v;solve(to,u);
26         per(j,min(s[u]+s[to],m),2)
27             rep(k,max(1,j-s[u]),min(s[to],j-1))
28                 Max(f[u][j],f[u][j-k]+f[to][k]);
29         s[u]+=s[to];
30     }
31 }
32 bool check(double val){
33     rep(i,1,n)
34         g[i]=v[i]-val*w[i];
35     rep(i,0,n)
36         rep(j,0,m)
37             f[i][j]=-1e9;
38     rep(i,0,n)
39         s[i]=1,f[i][1]=g[i];
40     solve(0,0);
41     return f[0][m]>=0;
42 }
43 int main(){
44     ios::sync_with_stdio(false);
45     cin.tie(0);cout.tie(0);
46     cin>>m>>n;m++;
47     rep(i,0,n)
48         head[i]=-1;
49     rep(i,1,n){
50         cin>>w[i]>>v[i];
51         int ff;cin>>ff,add(ff,i);
52     }
53     double l=0,r=1e4,eps=0.0003;
54     while(l+eps<=r){
55         double mid=(l+r)/2;
56         if(check(mid)) l=mid+eps;
57         else r=mid-eps;
58     }
59     cout<<fixed<<setprecision(3)<<l<<'\n';
60     return 0;
61 }
复制代码

四、写题心得:

  收获经验如下:

  1=>Exp++!

  2 O(n2) !=>Exp++!

posted on   trh0630  阅读(34)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示