Poj--1949(DAG,DP)
2014-12-11 13:45:49
思路:这题和今年暑假上海邀请赛那场的I题有异曲同工之妙,看似拓扑排序,其实可以用DAG上跑DP来找最长路来做。
可以有继承关系的事件必须分开做,所以两点建边(不建边说明可以同时做),且证明DAG上的最长路就是最终答案,因为任何其他过程都可以在最长路以内跑完。
1 /************************************************************************* 2 > File Name: 1949.cpp 3 > Author: Natureal 4 > Mail: 564374850@qq.com 5 > Created Time: Thu 11 Dec 2014 01:36:50 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <stack> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 const int INF = 1 << 30; 26 const int maxn = 10010; 27 28 int N; 29 int first[maxn],next[maxn * 100],ver[maxn * 100],ecnt; 30 int t[maxn]; 31 int dp[maxn]; 32 queue<int> Q; 33 34 void Init(){ 35 memset(first,-1,sizeof(first)); 36 ecnt = 0; 37 } 38 39 void Add_edge(int u,int v){ 40 next[++ecnt] = first[u]; 41 ver[ecnt] = v; 42 first[u] = ecnt; 43 } 44 45 int Solve(int p){ 46 if(dp[p]) 47 return dp[p]; 48 int res = 0; 49 for(int i = first[p]; i != -1; i = next[i]){ 50 int v = ver[i]; 51 res = max(res,Solve(v)); 52 } 53 return dp[p] = res + t[p]; 54 } 55 56 int main(){ 57 scanf("%d",&N); 58 Init(); 59 memset(dp,0,sizeof(dp)); 60 int num,pre; 61 for(int i = 1; i <= N; ++i){ 62 scanf("%d%d",&t[i],&num); 63 if(num == 0) 64 Q.push(i); 65 for(int j = 1; j <= num; ++j){ 66 scanf("%d",&pre); 67 Add_edge(pre,i); 68 } 69 } 70 int ans = 0; 71 while(!Q.empty()){ 72 int x = Q.front(); 73 Q.pop(); 74 ans = max(ans,Solve(x)); 75 } 76 printf("%d\n",ans); 77 return 0; 78 }