当前位置 博文首页 > 文章内容

    洛谷 U138543 湮灭的光

    作者: 栏目:未分类 时间:2020-11-14 15:01:15

    本站于2023年9月4日。收到“大连君*****咨询有限公司”通知
    说我们IIS7站长博客,有一篇博文用了他们的图片。
    要求我们给他们一张图片6000元。要不然法院告我们

    为避免不必要的麻烦,IIS7站长博客,全站内容图片下架、并积极应诉
    博文内容全部不再显示,请需要相关资讯的站长朋友到必应搜索。谢谢!

    另祝:版权碰瓷诈骗团伙,早日弃暗投明。

    相关新闻:借版权之名、行诈骗之实,周某因犯诈骗罪被判处有期徒刑十一年六个月

    叹!百花齐放的时代,渐行渐远!



    洛谷 U138543 湮灭的光

    洛谷传送门

    题目背景

    “我揭开了未来的面纱,却只看到了湮灭”

    题目描述

    在预言中,夏古拉斯炸毁后,星灵不久后就惨遭灭亡。

    为了避免自己族人灭亡,黑暗教长踏上了寻找其他预言碎片的道路。

    星系中分布着N块预言碎片,黑暗教长的总体力值为M。收集碎片不是一件易事。收集第i块预言碎片将消耗黑暗教长Ti的体力值。 而这些充满神秘文字的碎片间存在依赖关系,对于预言碎片i,只有收集了其前置碎片Di时,黑暗教长才能获得这枚碎片的信息值Wi。(若Di=0,则说明该预言碎片无前置碎片。多块碎片可互相为前置碎片。)。也就是说,对于碎片i,若直接收集i而不收集Di,i将毫无贡献。

    末日将近,时间紧迫。黑暗教长找到了JDOI的神——你。 他想知道在有限的体力内,能获得的最大信息值是多少

    输入格式

    第一行:N,M (0≤N≤100,0≤M≤500)

    第二行:N个整数,表示Ti (0≤Ti≤M)

    第三行:N个整数,表示Wi (0≤Wi≤1000)

    第四行:N个整数,表示Di(0≤Di≤N,Di=i)

    输出格式

    一个整数 表示黑暗教长能获得的最大能量


    题解:

    2020.11.14模拟赛T4。

    Tarjan缩点+建虚根树形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\n", dp[0][m]);
     	return 0;
    }