zoukankan      html  css  js  c++  java
  • BZOJ2427:[HAOI2010]软件安装(树形DP,强连通分量)

    Description

    现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi。我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大)。

    但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j)。幸运的是,一个软件最多依赖另外一个软件。如果一个软件不能正常工作,那么它能够发挥的作用为0。

    我们现在知道了软件之间的依赖关系:软件i依赖软件Di。现在请你设计出一种方案,安装价值尽量大的软件。一个软件只能被安装一次,如果一个软件没有依赖则Di=0,这时只要这个软件安装了,它就能正常工作。

    Input

    第1行:N, M  (0<=N<=100, 0<=M<=500)
    第2行:W1, W2, ... Wi, ..., Wn (0<=Wi<=M )
    第3行:V1, V2, ..., Vi, ..., Vn  (0<=Vi<=1000 )
    第4行:D1, D2, ..., Di, ..., Dn(0<=Di<=N, Di≠i )

    Output

    一个整数,代表最大价值。

    Sample Input

    3 10
    5 5 6
    2 3 4
    0 1 1

    Sample Output

    5

    Solution 

    首先按依赖关系建个图……然后tarjan缩个点……缩完后会是若干棵树的形态……
    将若干棵树连向一个根然后DP……设f[x][i]表示在x点装了空间i的最大价值……

    Code

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #define N (1000000+1000)
     5 using namespace std;
     6 
     7 struct Edge{int to,next;}edge[N];
     8 int Dfn[N],Low[N],Col[N],stack[N],Ind[N],top,dfs_num,col_num;
     9 int n,m,w[N],v[N],d[N],W[N],V[N],head[N],f[105][505],num_edge;
    10 bool vis[N];
    11 
    12 void add(int u,int v)
    13 {
    14     edge[++num_edge].to=v;
    15     edge[num_edge].next=head[u];
    16     head[u]=num_edge;
    17 }
    18 
    19 void Tarjan(int x)
    20 {
    21     Dfn[x]=Low[x]=++dfs_num;
    22     stack[++top]=x; vis[x]=true;
    23     for (int i=head[x]; i; i=edge[i].next)
    24         if (!Dfn[edge[i].to])
    25             Tarjan(edge[i].to),Low[x]=min(Low[x],Low[edge[i].to]);
    26         else if (vis[edge[i].to])
    27             Low[x]=min(Low[x],Dfn[edge[i].to]);
    28     if (Dfn[x]==Low[x])
    29     {
    30         vis[x]=false; Col[x]=++col_num;
    31         W[col_num]=w[x]; V[col_num]=v[x];
    32         while (stack[top]!=x)
    33         {
    34             vis[stack[top]]=false;
    35             Col[stack[top]]=col_num;
    36             W[col_num]+=w[stack[top]];
    37             V[col_num]+=v[stack[top--]];
    38         }
    39         --top;
    40     }
    41 }
    42 
    43 void DP(int x)
    44 {
    45     for(int i=head[x]; i; i=edge[i].next)
    46     {
    47         DP(edge[i].to);
    48         for(int j=m-W[x]; j>=0; --j)
    49             for(int k=0; k<=j; ++k)
    50                 f[x][j]=max(f[x][j],f[x][k]+f[edge[i].to][j-k]);        
    51     }
    52     for(int j=m;j>=0;j--)
    53     {
    54         if(j>=W[x]) f[x][j]=f[x][j-W[x]]+V[x];
    55         else f[x][j]=0;
    56     }
    57 }
    58 
    59 int main()
    60 {
    61     scanf("%d%d",&n,&m);
    62     for (int i=1; i<=n; ++i) scanf("%d",&w[i]);
    63     for (int i=1; i<=n; ++i) scanf("%d",&v[i]);
    64     for (int i=1; i<=n; ++i) 
    65     {
    66         scanf("%d",&d[i]);
    67         if (d[i]) add(d[i],i);
    68     }
    69     for (int i=1; i<=n; ++i)
    70         if (!Dfn[i]) Tarjan(i);
    71     
    72     memset(head,0,sizeof(head)); num_edge=0;
    73     for (int i=1; i<=n; ++i)
    74         if (d[i] && Col[i]!=Col[d[i]])
    75             add(Col[d[i]],Col[i]),Ind[Col[i]]++;
    76     for (int i=1; i<=col_num; ++i)
    77         if (!Ind[i]) add(col_num+1,i);
    78     DP(col_num+1);
    79     printf("%d
    ",f[col_num+1][m]);
    80 }
  • 相关阅读:
    noi 2011 noi嘉年华 动态规划
    最小乘积生成树
    noi 2009 二叉查找树 动态规划
    noi 2010 超级钢琴 划分树
    noi 2011 阿狸的打字机 AC自动机
    noi 2009 变换序列 贪心
    poj 3659 Cell Phone Network 动态规划
    noi 2010 航空管制 贪心
    IDEA14下配置SVN
    在SpringMVC框架下建立Web项目时web.xml到底该写些什么呢?
  • 原文地址:https://www.cnblogs.com/refun/p/9609598.html
Copyright © 2011-2022 走看看