Bzoj2427: [HAOI2010]软件安装

思路:Tarjan找环,缩点。然后再进行树上背包问题

注意两套图不要用混了

/**************************************************************
    Problem: 2427
    User: Bj2002
    Language: C++
    Result: Accepted
    Time:212 ms
    Memory:1500 kb
****************************************************************/
 
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
#include <fstream>
#define re register
#define GC getchar()
#define Clean(X,K) memset(X,K,sizeof(X))
#define Min(X,Y) ((X)<(Y)?(X):(Y))
#define Max(X,Y) ((X)>(Y)?(X):(Y))
#include <iostream>
using namespace std ;
int Qread () {
    int X = 0 ;
    char C = GC ;
    while (C > '9' || C < '0') C = GC ;
    while (C >='0' && C <='9') {
        X = X * 10 + C - '0' ;
        C = GC ;
    }
    return X ;
}
const int Maxn = 105 , Maxm = 505 , INF = 20021020 << 2;
int Ind[Maxn] , F[Maxn][Maxm] , En = 0 , Head[Maxn] , C = 0 , Cor[Maxn] , Vis[Maxn] , St[Maxn] , Top = 0 , N , M , w[Maxn] ,W[Maxn] ,  v[Maxn] , V[Maxn] , D[Maxn] , Cnt = 0 , Low[Maxn] , Dfn[Maxn];
struct Edge {
    int From_Point , Goto_Point , Next_Edge ;
};
Edge E[Maxn] ;
void Tarjan (int X) {
    Low[X] = Dfn[X] = ++ Cnt ;
    Vis[X] = 1 ;
    St[++ Top] = X ;
    if (D[X]) {
        if (!Dfn[D[X]]) {
            Tarjan (D[X]) ;
            Low[X] = Min (Low[X] , Low[D[X]]) ;
        } else if (Vis[D[X]]) Low[X] = Min (Low[X] , Dfn[D[X]]) ;
    }
    if (Low[X] == Dfn[X]) {
        ++ C ;
        while (St[Top] != X) {
            V[C] += v[St[Top]] ;
            W[C] += w[St[Top]] ;
            Vis[St[Top]] = 0 ;
            Cor[St[Top]] = C ;
            -- Top ;
        }
        V[C] += v[X] ;
        W[C] += w[X] ;
        Cor[X] = C ;
        Vis[X] = 0 ;
        -- Top ;
    }
}
void Adg (int X , int Y) {
    E[++En].From_Point = X ;
    E[En].Goto_Point = Y ;
    E[En].Next_Edge = Head[X] ;
    Head[X] = En ;
}
void DFS (int X) {
    for (re int i = Head[X] ; i ; i = E[i].Next_Edge ) {
        DFS (E[i].Goto_Point ) ; 
        for (re int j = M ; j >= 0 ; -- j) for (re int k = 0 ; k <=j ; ++ k) F[X][j] = Max (F[X][j] , F[X][j - k] + F[E[i].Goto_Point ][k]) ;
    }
    for (re int i = M ; i >= W[X] ; -- i) F[X][i] = F[X][i - W[X]] + V[X] ;
    for (re int i = W[X] - 1; i >= 0 ; -- i) F[X][i] = 0 ;
}
int main () {
//  freopen ("P2515.in" , "r" , stdin) ;
//  freopen ("my.out" , "w" , stdout) ;
    N = Qread () , M = Qread () ;
    for (re int i = 1 ; i <= N; ++ i) w[i] = Qread () ;
    for (re int i = 1 ; i <= N; ++ i) v[i] = Qread () ;
    for (re int i = 1 ; i <= N; ++ i) D[i] = Qread () ;
    for (re int i = 1 ; i <= N; ++ i) if (!Dfn[i]) Tarjan(i) ;
    Clean(Head , 0) , Clean (F , 0) ;
    for (re int i = 1 ; i <= N; ++ i) if (Cor[i] != Cor[D[i]] && D[i]) {
            if (!F[Cor[D[i]]][Cor[i]]) {
                Adg (Cor[D[i]] , Cor[i]) ;
                ++ Ind[Cor[i]] ;
                F[Cor[D[i]]][Cor[i]] = INF ;
            }
        }
    V[0] = 0 , W[0] = 0 ;
    for (re int i = 1 ; i <= C; ++ i) if (!Ind[i]) Adg (0 , i) ;
    Clean(F , 0) ;
    DFS (0) ;
    cout << F[0][M]<<endl;
    fclose (stdin) , fclose (stdout) ;
    return 0 ;
}

 

posted @ 2019-04-03 19:00  Betulaceae  阅读(153)  评论(0编辑  收藏  举报