缩点+树形 DP 求助
查看原帖
缩点+树形 DP 求助
134000
Plozia楼主2021/5/11 19:30
/*
========= Plozia =========
    Author:Plozia
    Problem:P2515 [HAOI2010]软件安装
    Date:2021/5/11
========= Plozia =========
*/

#include <bits/stdc++.h>

typedef long long LL;
const int MAXN = 100 + 10, MAXM = 500 + 10;
int n, m, f[MAXN][MAXM], d[MAXN], sta[MAXN], Top, col[MAXN], Color, cnt_a;
bool book[MAXN];

struct Graph
{
    int w[MAXN], v[MAXN];
    int Head[MAXN], cnt_Edge = 1;
    struct node { int to, val, Next; } Edge[MAXN << 1];
    void add_Edge(int x, int y, int z) { ++cnt_Edge; Edge[cnt_Edge] = (node){y, z, Head[x]}; Head[x] = cnt_Edge; }
}og, ng;//Old_Graph, New_Graph

struct EDGE { int x, y; } a[MAXN << 1];

int read()
{
    int sum = 0, fh = 1; char ch = getchar();
    for (; ch < '0' || ch > '9'; ch = getchar()) fh -= (ch == '-') << 1;
    for (; ch >= '0' && ch <= '9'; ch = getchar()) sum = (sum << 3) + (sum << 1) + (ch ^ 48);
    return sum * fh;
}
int Max(int fir, int sec) { return (fir > sec) ? fir : sec; }
int Min(int fir, int sec) { return (fir < sec) ? fir : sec; }
bool cmp(const EDGE &fir, const EDGE &sec) { return (fir.x ^ sec.x) ? (fir.x < sec.x) : (fir.y < sec.y); }

void dfs1(int now)
{
    book[now] = 1;
    for (int i = og.Head[now]; i; i = og.Edge[i].Next)
    {
        int u = og.Edge[i].to;
        if (book[u] || og.Edge[i].val == 0) continue ;
        dfs1(u);
    }
    ++Top; sta[Top] = now;
}

void dfs2(int now)
{
    book[now] = 1; col[now] = Color;
    for (int i = og.Head[now]; i; i = og.Edge[i].Next)
    {
        int u = og.Edge[i].to;
        if (book[u] || og.Edge[i].val == 1) continue ;
        dfs2(u);
    }
}

void DP(int now, int father)
{
    if (ng.Head[now] == 0) { for(int i = ng.w[now]; i <= m; ++i) f[now][i] = ng.v[now]; return ; }
    for (int i = ng.Head[now]; i; i = ng.Edge[i].Next)
    {
        int u = ng.Edge[i].to;
        if (u == father) continue ;
        DP(u, now);
        for (int j = 0; j <= m; ++j)
            if (j >= ng.w[now]) f[now][j] = Max(f[now][j], f[u][j - ng.w[now]] + ng.v[now]);
            else f[now][j] = Max(f[now][j], f[u][j]);
    }
}

int main()
{
    n = read(), m = read();
    for (int i = 1; i <= n; ++i) og.w[i] = read();
    for (int i = 1; i <= n; ++i) og.v[i] = read();
    for (int i = 1; i <= n; ++i) d[i] = read();
    for (int i = 1; i <= n; ++i) { og.add_Edge(d[i], i, 1); og.add_Edge(i, d[i], 0); }
    for (int i = 0; i <= n; ++i)
        if (!book[i]) dfs1(i);
    memset(book, 0, sizeof(book));
    std::reverse(sta + 1, sta + Top + 1);
    for (int i = 1; i <= Top; ++i)
        if (!book[sta[i]]) { ++Color; dfs2(sta[i]); }
    for (int i = 2; i <= og.cnt_Edge; i += 2)
    {
        int x = og.Edge[i ^ 1].to, y = og.Edge[i].to;
        if (col[x] != col[y]) { ++cnt_a; a[cnt_a] = (EDGE){col[x], col[y]}; }
    }
    std::sort(a + 1, a + cnt_a + 1, cmp);
    for (int i = 2; i <= cnt_a; ++i)
    {
        if (a[i].x == a[i - 1].x && a[i].y == a[i - 1].y) continue ;
        ng.add_Edge(a[i].x, a[i].y, 0);
    }
    for (int i = 0; i <= Color; ++i) ng.add_Edge(Color + 1, i, 0);
    for (int i = 0; i <= n; ++i) { ng.w[col[i]] += og.w[i]; ng.v[col[i]] += og.v[i]; }
    DP(Color + 1, Color + 1); printf("%d\n", f[Color + 1][m]); return 0;
}
2021/5/11 19:30
加载中...