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

    [HAOI2010]软件安装

    分析:

    每个点最多依赖一个点,最后建出来的图可能成环,也可能是一棵树。

    先用tarjan缩点,对缩点后的图建边,会建成一颗森林(有成环点缩点后孤立)

    用一个超级源点向入度为0的点连边,跑一遍树形dp

    注意:
    1. 弄清楚依赖关系

    2. 树形dp中要固定选父节点

    #include<bits/stdc++.h>
    using namespace std;
    #define N 105
    #define ri register int
    int to[N],nex[N],head[N],tot=0,dp[N][N*5],flag[N],n,m,ru[N];
    int dfn[N],low[N],stk[N],Ti=0,cnt=0,bel[N],w1[N],v1[N],w2[N],v2[N],top=0;
    vector<int> e[N];
    vector<int> scc[N];
    void add(int a,int b) { to[++tot]=b; nex[tot]=head[a]; head[a]=tot; }
    void tarjan(int x)
    {
        dfn[x]=low[x]=++Ti;
        stk[++top]=x; flag[x]=true;
        for(ri i=head[x];i;i=nex[i]){
            int v=to[i];
            if(!dfn[v]){
                tarjan(v);
                low[x]=min(low[x],low[v]);
            }
            else if(flag[v]) low[x]=min(low[x],dfn[v]);
        }
        if(low[x]==dfn[x]){
            cnt++;
            do{
                int tmp=stk[top];
                scc[cnt].push_back(tmp); flag[tmp]=0;
                bel[tmp]=cnt;
            }while(stk[top--]!=x);
        }
    }
    void dfs(int u)
    {
        for(ri i=v2[u];i<=m;++i) dp[u][i]=w2[u];
        for(ri i=0;i<e[u].size();++i){
            int v=e[u][i];
            dfs(v);
            for(ri j=m;j>=v2[u];--j)
             for(ri k=0;k<=j-v2[u];++k)//j-v2[u]固定了一定会选到父节点!! 
              dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]);
        }
    }
    int main()
    {
        int d;
        scanf("%d%d",&n,&m);
        for(ri i=1;i<=n;++i) scanf("%d",&v1[i]);
        for(ri i=1;i<=n;++i) scanf("%d",&w1[i]);
        for(ri i=1;i<=n;++i) { scanf("%d",&d); if(d) add(d,i); }
        for(ri i=1;i<=n;++i) if(!dfn[i]) tarjan(i);
        for(ri i=1;i<=n;++i){
            w2[bel[i]]+=w1[i]; v2[bel[i]]+=v1[i];
            for(ri j=head[i];j;j=nex[j]){
                int v=to[j];
                if(bel[i]!=bel[v])
                 e[bel[i]].push_back(bel[v]),ru[bel[v]]++;
            }
        }
        for(ri i=1;i<=cnt;++i) if(!ru[i]) e[cnt+1].push_back(i);
        dfs(cnt+1);
        printf("%d",dp[cnt+1][m]);/**/
    }
    /*
    3 10
    5 5 6
    2 3 4
    0 1 1
    */
    View Code
  • 相关阅读:
    ACM ICPC 2008–2009 NEERC MSC A, B, C, G, L
    POJ 1088 滑雪 DP
    UVA 11584 最短回文串划分 DP
    POJ 2531 Network Saboteur DFS+剪枝
    UVa 10739 String to Palindrome 字符串dp
    UVa 11151 Longest Palindrome 字符串dp
    UVa 10154 Weights and Measures dp 降维
    UVa 10271 Chopsticks dp
    UVa 10617 Again Palindrome 字符串dp
    UVa 10651 Pebble Solitaire 状态压缩 dp
  • 原文地址:https://www.cnblogs.com/mowanying/p/11656382.html
Copyright © 2011-2022 走看看