zoukankan      html  css  js  c++  java
  • 洛谷 P2515 [HAOI2010]软件安装

    洛谷 P2515 [HAOI2010]软件安装

    洛谷传送门

    题目描述

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

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

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

    输入格式

    第1行:N,M(0leq Nleq 100, 0leq Mleq 500)N,M(0≤N≤100,0≤M≤500)

    第2行:W_1,W_2, ... W_i, ..., W_n (0leq W_ileq M)W1,W2,...W**i,...,W**n(0≤W**iM)

    第3行:V_1, V_2, ..., V_i, ..., V_n (0leq V_ileq 1000)V1,V2,...,V**i,...,V**n(0≤V**i≤1000)

    第4行:D_1, D_2, ..., D_i, ..., D_n (0leq D_ileq N, D_i≠i)D1,D2,...,D**i,...,D**n(0≤D**iN,D**i�=i)

    输出格式

    一个整数,代表最大价值


    题解:

    2020.11.14模拟赛T4 10pts场。。。

    蒟蒻太菜啦!

    明明考场上想到了是缩点,但是不会拍Tarjan了...蒟蒻太菜啦

    所以只拿了10pts的全裸背包暴力。

    其实如果DAG给些分,还能多拿。

    所以简单讲一下思路:

    首先能发现的性质是:对于一个有向环,选就得全选,不选就都不能选。所以这就是一个大号的点。

    所以要Tarjan等效缩点啊。然后再建虚节点0把所有连通块连一起。就可以树形DP了。

    代码:

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    const int maxn = 505;
    int n, m, cnt, w[maxn], a[maxn], d[maxn]; 
    int dfn[maxn], low[maxn], bel[maxn], tot, scc, ins[maxn], sta[maxn], top; 
    int W[maxn], V[maxn], indag[maxn], dp[maxn][maxn];
    struct edge {
        int v;
        edge *next;
    }pool[maxn * 2], *head[maxn];
    inline void add(int u, int v) {
        edge *p = &pool[++cnt];
        p->v = v, p->next = head[u], head[u] = p; 
    }
    void tarjan(int u) {
        dfn[u] = low[u] = ++tot; sta[++top] = u; ins[u] = 1;
        for(edge *p = head[u]; p; p = p->next) {
            int v = p->v;
            if(!dfn[v]) {
                tarjan(v); 
                low[u] = min(low[u], low[v]);
            } else if(ins[v]) 
                low[u] = min(low[u], dfn[v]);
        }
        if(dfn[u] == low[u]) {
            ++scc;
            while(sta[top + 1] != u) {
                bel[sta[top]] = scc;
                W[scc] += w[sta[top]]; 
                V[scc] += a[sta[top]];
                ins[sta[top--]] = 0;
            }
        }
    }
    void solve(int u) 
    {
        for(int i = W[u]; i <= m; i++)
            dp[u][i] = V[u];
        for(edge *p = head[u]; p; p = p->next) 
    	{
            int v = p->v;
            solve(v); int k = m - W[u];
            for(int i = k; i >= 0; i--) 
                for(int j = 0; j <= i; j++)
                    dp[u][i + W[u]] = max(dp[u][i + W[u]], dp[v][j] + dp[u][i + W[u] - j]);
        }
    }
    int main()
    {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i++) 
    		scanf("%d", &w[i]);
        for(int i = 1; i <= n; i++) 
    		scanf("%d", &a[i]);
        for(int i = 1; i <= n; i++) 
    	{
        	scanf("%d", &d[i]); 
    		if(d[i]) 
    			add(d[i], i);
        }
        for(int i = 1; i <= n; i++)    
            if(!dfn[i]) tarjan(i);
        for(int i = 0; i <= n; i++) 
    		head[i] = 0; 
    	cnt = 0;
        for(int i = 1; i <= n; i++)
        	if(bel[d[i]] != bel[i]) 
    		{
        		add(bel[d[i]], bel[i]);
        		indag[bel[i]]++;
            }
        for(int i = 1; i <= scc; i++) 
            if(!indag[i]) 
    			add(0, i);
        solve(0);
        printf("%d
    ", dp[0][m]);
     	return 0;
    }
    
  • 相关阅读:
    前端神器avalonJS入门(一)
    emmet的使用
    VS2015中SharedProject与可移植类库(PCL)项目
    Map工具系列-08-map控件查看器
    Map工具系列-07-TFS变更集提取工具
    Map工具系列-06-销售营改增历史数据处理工具
    2018.04.02 matplotlib 图名,图例,轴标签,轴边界,轴刻度,轴刻度标签
    2018.03.30 abap屏幕标签保存之前执行过的状态
    2018.03.29 python-matplotlib 图表生成
    2018.03.29 python-pandas 数据读取
  • 原文地址:https://www.cnblogs.com/fusiwei/p/13973246.html
Copyright © 2011-2022 走看看