Live2D

[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\n",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\n",dp[num+1][m]);
151     return 0;
152
posted @ 2018-07-03 21:13  ztz11  阅读(269)  评论(0编辑  收藏  举报