zoukankan      html  css  js  c++  java
  • HAOI2010 软件安装

    传送门

    一开始我以为这道题是一个比较正常的分组背包,只不过原来做的题目的限制条件是数目,这次是有体积(软件所占空间)的限制,但是两者好像没什么差异……

    于是我就仿着正常的分组背包写了一下,然后过了样例。我才不会告诉你我一开始结果全是0,因为我写错了

    交上去一看只有10分……

    回来发现原来这题并没有说是一棵树……orz,那我们来看一看每一个环,每个环里面所有的软件要么全选,要么全不选,所以直接看成一个强连通分量缩点,把体积和价值都合起来即可。就像炉石那张融合所以我们缩点,之后把所有入度为0的点向虚拟节点连边,之后开始正常DP。但是我一开始发现建出来的图是反的,这样就行不成树了。不过想起了tarjan求强连通分量的时候,因为我把树建成了有向图,所以肯定原来的起点现在还应该是起点,就把建图反了过来,之后就神奇的AC啦!

    看一下代码。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<set>
    #include<queue>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    
    using namespace std;
    typedef long long ll;
    const int M = 1005;
    const int INF = 1000000009;
    const ll mod = 1e9+7;
    
    int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
        if(ch == '-') op = -1;
        ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
        ans *= 10;
        ans += ch - '0';
        ch = getchar();
        }
        return ans * op;
    }
    
    struct node
    {
        int next,to,from;
    }e[M<<1];
    
    int m,n,dp[M][M],v[M],x,y,head[M],ecnt,size[M],w[M],dfn[M],scc[M],idx,low[M],stack[M],top,cnt;
    int rdeg[M],tot;
    bool vis[M];
    
    void add(int x,int y)
    {
        e[++ecnt].to = y;
        e[ecnt].next = head[x];
        e[ecnt].from = x;
        head[x] = ecnt;
    }
    
    void tarjan(int x)
    {
        low[x] = dfn[x] = ++idx;
        stack[++top] = x,vis[x] = 1;
        for(int i = head[x];i;i = e[i].next)
        {
        if(!dfn[e[i].to]) tarjan(e[i].to),low[x] = min(low[x],low[e[i].to]);
        else if(vis[e[i].to]) low[x] = min(low[x],dfn[e[i].to]);
        }
        if(low[x] == dfn[x])
        {
        int p;
        cnt++;
        while((p = stack[top--]))
        {
            scc[p] = cnt,vis[p] = 0,v[cnt] += v[p],w[cnt] += w[p];
            if(p == x) break;
        }
        }
    }
    
    void rebuild()
    {
        rep(i,1,ecnt)
        {
        int r1 = scc[e[i].from],r2 = scc[e[i].to];
        if(r1 != r2) add(r2,r1),rdeg[r1]++;
        }
        rep(i,n+1,cnt)
        {
        dp[i][0] = v[i];
        if(!rdeg[i]) add(0,i);
        }
    }
    
    void dfs(int x,int fa)
    {
        for(int i = head[x];i;i = e[i].next)
        {
        int t = e[i].to;
        if(t == fa) continue;
        dfs(t,x);
        per(j,m,1)
        {
            rep(p,0,j-w[t]) dp[x][j] = max(dp[x][j],dp[x][j-p-w[t]] + dp[t][p]);
        }
        //rep(j,0,m) printf("%d ",dp[x][j]);enter;
        //printf("#%d %d
    ",x,dp[x][0]);
        }
    }
    
    int main()
    {
        n = read(),m = read();
        rep(i,1,n) w[i] = read();
        rep(i,1,n) v[i] = read();
        rep(i,1,n)
        {
        x = read();
        if(x != 0) add(i,x);
        }
        cnt = n,tot = ecnt;
        rep(i,1,n) if(!dfn[i]) tarjan(i);
        rebuild();
        //rep(i,tot+1,ecnt) printf("%d %d
    ",e[i].from,e[i].to);
        dfs(0,0);
        printf("%d
    ",dp[0][m]);
        return 0;
    }
  • 相关阅读:
    Freemaker:操作集合
    win10:在关闭防火墙下如何屏蔽特定端口
    win10:家庭版开启组策略
    oracle:10g下载地址(转载)
    mybatis:延迟加载时不要在get/set方法上面添加final关键字(原创)
    mybatis:在springboot中的配置
    mybatis:访问静态变量或方法
    maven:手动安装JAR到本地仓库
    datatables日常使用集合
    python 装饰器
  • 原文地址:https://www.cnblogs.com/captain1/p/9814356.html
Copyright © 2011-2022 走看看