思路: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 ; }