HAOI2010 软件安装

为获得更好地阅读体验请访问我的 Blog

Luogu

这题开始我 WA40 了一个晚上。。。后来才发现是重建图的时候没有判断自环的情况

因为可能是有环的,所以用 Tarjan 将所有的环都缩起来,然后跑树形DP。

不知道 Luogu 上是怎么给到紫色难度的。。。

#include <iostream>
#include <cstdio>
#include <vector>
#include <stack>

const int MaxN = 500 + 5;
const int MaxM = 500 + 5;

int N, M, Scc, Idx;
int W[MaxN], V[MaxN], D[MaxN], WS[MaxN], VS[MaxN], Dfn[MaxN], Low[MaxN], Belong[MaxN], Dp[MaxN][MaxM], Indegree[MaxN];
bool InStack[MaxN], Book[MaxN][MaxN];
std::vector <int> Linker[MaxN];
std::stack <int> S;

inline int read()
{
    register int x = 0;
    register char ch = getchar();
    while(!isdigit(ch)) ch = getchar();
    while(isdigit(ch))
    {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x;
}

void Tarjan(int cur)
{
    Dfn[cur] = Low[cur] = ++Idx;
    S.push(cur);
    InStack[cur] = 1;
    for(auto to : Linker[cur])
    {
        if(!Dfn[to])
        {
            Tarjan(to);
            Low[cur] = std::min(Low[cur], Low[to]);
        }
        else if(InStack[to]) Low[cur] = std::min(Low[cur], Dfn[to]);
    }
    if(Dfn[cur] == Low[cur])
    {
        ++Scc;
        int t;
        do
        {
            t = S.top();
            S.pop();
            InStack[t] = 0;
            Belong[t] = Scc;
            WS[Scc] += W[t];
            VS[Scc] += V[t];
        }
        while(t != cur);
    }
}

void DP(int cur)
{
    for(auto to : Linker[cur])
    {
        DP(to);
        for(int i = M - WS[cur]; i >= 1; --i)
            for(int j = 0; j <= i; ++j) Dp[cur][i] = std::max(Dp[cur][i], Dp[cur][i - j] + Dp[to][j]);
    }
    for(int i = M; i >= WS[cur]; --i) Dp[cur][i] = Dp[cur][i - WS[cur]] + VS[cur];
    for(int i = WS[cur] - 1; i >= 0; --i) Dp[cur][i] = 0;
}

int main()
{
    N = read();
    M = read();
    for(int i = 1; i <= N; ++i) W[i] = read();
    for(int i = 1; i <= N; ++i) V[i] = read();
    for(int i = 1; i <= N; ++i) 
    {
        D[i] = read();
        if(!D[i]) continue;
        Linker[D[i]].push_back(i);
    }
    for(int i = 1; i <= N; ++i) if(!Dfn[i]) Tarjan(i);
    for(int i = 0; i <= N; ++i) Linker[i].clear();
    int t = 0;
    for(int i = 1; i <= N; ++i)
    {
        if(!Book[Belong[i]][Belong[D[i]]] && Belong[i] != Belong[D[i]])
        {
            Book[Belong[i]][Belong[D[i]]] = 1;
            Linker[Belong[D[i]]].push_back(Belong[i]);
            ++Indegree[Belong[i]];
            ++t;
        }
    }
    for(int i = 1; i <= Scc; ++i) if(!Indegree[i]) Linker[0].push_back(i);
    DP(0);
    printf("%d\n", Dp[0][M]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zcdhj/p/9440742.html
今日推荐