zoukankan      html  css  js  c++  java
  • [HAOI2010]软件安装(树形背包,tarjan缩点)

    题目描述

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

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

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

    输入输出格式

    输入格式:

    第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 )

    输出格式:

    一个整数,代表最大价值

    思路:

    望过去满眼的树形DP

    和前面写的选课一模一样,只是cost需要输入

    但很显然,你会这样

    为什么呢?

    后来想了半天,才发现

    如果1依赖于2,2依赖于2,3依赖于1的化,这几个个点其实也能选,不过要选得一起选

    所以,我们要用tarjan来缩点

     把所有满足上图关系的点变为一个新点,并且与0连边即可

    Q:环套树怎么办?

    因为一个点只唯一依赖另一个点,所以入边一定为1

    所以一定是环到树,不可能树到环,所以缩点没问题

    懒了一下,用了stl

    代码:

    // luogu-judger-enable-o2
    #include<iostream>
    #include<stack>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #define rii register int i
    #define rij register int j
    #define rik register int k
    using namespace std;
    const int N=105;const int M=505;
    struct E{
        int to,nxt;
    }ed[N<<1];
    int H[N<<1],cnt;
    stack<int>sta;
    bool ins[N];
    int dp[N][M],v[N],w[N],d[N];
    int tot,dfn[N],low[N];
    int num,col[N],fv[N],fw[N];
    int n,m,rd[N];
    void add(int x,int y)
    {
        cnt++;
        ed[cnt].to=y;
        ed[cnt].nxt=H[x];
        H[x]=cnt;
        return;
    }
    void read(int &in)
    {
        int x=0,f=1;
        char ch;
        for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
        if(ch=='-')
        {
            f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            x=(x<<3)+(x<<1)+ch-'0';
            ch=getchar();
        }
        in=x*f;
        return;
    }
    void tarjan(int x)
    {
        dfn[x]=low[x]=++tot;
        ins[x]=true;sta.push(x);
        int t,k;
        for(rii=H[x];i;i=ed[i].nxt)
        {
            t=ed[i].to;
            if(!dfn[t])
            {
                tarjan(t);
                low[x]=min(low[x],low[t]);
            }
            else if(ins[t])
            {
                low[x]=min(low[x],dfn[t]);
            }
        }
        if(low[x]==dfn[x])
        {
            num++;
            do
            {
                k=sta.top();
                sta.pop();
                col[k]=num;
                fw[num]+=w[k];
                fv[num]+=v[k];
                ins[k]=false;
            }
            while(k!=x);
        }
        return;
    }
    void dfs(int x)
    {
        for(rii=fw[x];i<=m;i++)
        {
            dp[x][i]=fv[x];
        }
        int t;
        for(rii=H[x];i;i=ed[i].nxt)
        {
            t=ed[i].to;
            dfs(t);
            for(rij=m-fw[x];j>=0;j--)
            {
                for(rik=0;k<=j;k++)
                {
                    dp[x][j+fw[x]]=max(dp[x][j+fw[x]],dp[x][j+fw[x]-k]+dp[t][k]);
                }
            }
        }
        return;
    }
    int main()
    {
    //     freopen("software.in","r",stdin);
    //     freopen("software.out","w",stdout);
        read(n);
        read(m);
        for(rii=1;i<=n;i++)
        {
            read(w[i]);
        }
        for(rii=1;i<=n;i++)
        {
            read(v[i]);
        }
        for(rii=1;i<=n;i++)
        {
            read(d[i]);
            if(d[i])
            {
                add(d[i],i);
            }
        }
        for(rii=1;i<=n;i++)
        {
            if(!dfn[i])
            {
                tarjan(i);
            }
        }
        memset(H,0,sizeof(H));
        cnt=0;
        for(rii=1;i<=n;i++)
        {
            if(col[i]!=col[d[i]]&&d[i])
            {
            add(col[d[i]],col[i]);
            rd[col[i]]++;
            }
        }
        for(rii=1;i<=num;i++)
        {
            if(!rd[i])
            {
                add(num+1,i);
            }
            dfs(num+1);
        }
        printf("%d
    ",dp[num+1][m]);
        return 0;
    }
      1 // luogu-judger-enable-o2
      2 #include<iostream>
      3 #include<stack>
      4 #include<cstdio>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #define rii register int i
      8 #define rij register int j
      9 #define rik register int k
     10 using namespace std;
     11 const int N=105;const int M=505;
     12 struct E{
     13     int to,nxt;
     14 }ed[N<<1];
     15 int H[N<<1],cnt;
     16 stack<int>sta;
     17 bool ins[N];
     18 int dp[N][M],v[N],w[N],d[N];
     19 int tot,dfn[N],low[N];
     20 int num,col[N],fv[N],fw[N];
     21 int n,m,rd[N];
     22 void add(int x,int y)
     23 {
     24     cnt++;
     25     ed[cnt].to=y;
     26     ed[cnt].nxt=H[x];
     27     H[x]=cnt;
     28     return;
     29 }
     30 void read(int &in)
     31 {
     32     int x=0,f=1;
     33     char ch;
     34     for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
     35     if(ch=='-')
     36     {
     37         f=-1;
     38         ch=getchar();
     39     }
     40     while(ch>='0'&&ch<='9')
     41     {
     42         x=(x<<3)+(x<<1)+ch-'0';
     43         ch=getchar();
     44     }
     45     in=x*f;
     46     return;
     47 }
     48 void tarjan(int x)
     49 {
     50     dfn[x]=low[x]=++tot;
     51     ins[x]=true;sta.push(x);
     52     int t,k;
     53     for(rii=H[x];i;i=ed[i].nxt)
     54     {
     55         t=ed[i].to;
     56         if(!dfn[t])
     57         {
     58             tarjan(t);
     59             low[x]=min(low[x],low[t]);
     60         }
     61         else if(ins[t])
     62         {
     63             low[x]=min(low[x],dfn[t]);
     64         }
     65     }
     66     if(low[x]==dfn[x])
     67     {
     68         num++;
     69         do
     70         {
     71             k=sta.top();
     72             sta.pop();
     73             col[k]=num;
     74             fw[num]+=w[k];
     75             fv[num]+=v[k];
     76             ins[k]=false;
     77         }
     78         while(k!=x);
     79     }
     80     return;
     81 }
     82 void dfs(int x)
     83 {
     84     for(rii=fw[x];i<=m;i++)
     85     {
     86         dp[x][i]=fv[x];
     87     }
     88     int t;
     89     for(rii=H[x];i;i=ed[i].nxt)
     90     {
     91         t=ed[i].to;
     92         dfs(t);
     93         for(rij=m-fw[x];j>=0;j--)
     94         {
     95             for(rik=0;k<=j;k++)
     96             {
     97                 dp[x][j+fw[x]]=max(dp[x][j+fw[x]],dp[x][j+fw[x]-k]+dp[t][k]);
     98             }
     99         }
    100     }
    101     return;
    102 }
    103 int main()
    104 {
    105 //     freopen("software.in","r",stdin);
    106 //     freopen("software.out","w",stdout);
    107     read(n);
    108     read(m);
    109     for(rii=1;i<=n;i++)
    110     {
    111         read(w[i]);
    112     }
    113     for(rii=1;i<=n;i++)
    114     {
    115         read(v[i]);
    116     }
    117     for(rii=1;i<=n;i++)
    118     {
    119         read(d[i]);
    120         if(d[i])
    121         {
    122             add(d[i],i);
    123         }
    124     }
    125     for(rii=1;i<=n;i++)
    126     {
    127         if(!dfn[i])
    128         {
    129             tarjan(i);
    130         }
    131     }
    132     memset(H,0,sizeof(H));
    133     cnt=0;
    134     for(rii=1;i<=n;i++)
    135     {
    136         if(col[i]!=col[d[i]]&&d[i])
    137         {
    138         add(col[d[i]],col[i]);
    139         rd[col[i]]++;
    140         }
    141     }
    142     for(rii=1;i<=num;i++)
    143     {
    144         if(!rd[i])
    145         {
    146             add(num+1,i);
    147         }
    148         dfs(num+1);
    149     }
    150     printf("%d
    ",dp[num+1][m]);
    151     return 0;
    152
  • 相关阅读:
    Python父类调用子类
    Python中for else注意事项
    JS Number类型数字位数及IEEE754标准
    cocos打包到ios与android上音频推荐
    JS学习之预解析(执行上下文)
    JS学习之函数的作用域
    JS学习之函数二
    JS学习之函数
    如何在subline中高亮显示.vue文件
    JS之正则
  • 原文地址:https://www.cnblogs.com/ztz11/p/9260669.html
Copyright © 2011-2022 走看看