1. 程式人生 > >luogu P2607 [ZJOI2008] 騎士 樹dp

luogu P2607 [ZJOI2008] 騎士 樹dp

傳送門

又一個沒有上司的舞會

這個dp有環 媽媽怎麼辦啊

要不...環上隨便斷一條邊?

然後最後選的時候分別取兩個根節點不選的情況的最大值

幾個要點:

1.圖可能是多個環套樹 要迴圈走完

2.不能只記錄頂點 因為如果有重邊的話會把二元環篩掉

3.位運算優先順序... 要寫成(i^1)==cntline

Time cost inf

這題從上週就開始D

一度放棄 今天想整一下以前做過的所有題然後就

就寫出來啦!!(開心)

Code:

(邊界寫的比較奇怪 是Debug的時候被嚇怕了)

 1
#include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 #include<vector> 6 #define ms(a,b) memset(a,b,sizeof a) 7 #define inf 2147483647 8 #define rep(i,a,n) for(int i = a;i <= n;i++) 9 #define per(i,n,a) for(int i = n;i >= a;i--) 10
using namespace std; 11 typedef long long ll; 12 int read() { 13 int as = 0,fu = 1; 14 char c = getchar(); 15 while(c<'0'||c>'9') { 16 if(c == '-') fu = -1; 17 c = getchar(); 18 } 19 while(c<='9'&&c>='0') { 20 as = as * 10 + c - '0'; 21 c = getchar();
22 } 23 return as * fu; 24 } 25 const int N = 1000005; 26 //head 27 int n; 28 int head[N],nxt[N<<1],mo[N<<1],cnt = -1; 29 void _add(int x,int y) { 30 mo[++cnt] = y; 31 nxt[cnt] = head[x]; 32 head[x] = cnt; 33 } 34 void add(int x,int y) {if(x^y)_add(x,y),_add(y,x);} 35 36 int rt1,rt2,Cntline; 37 bool vis[N]; 38 void dfs(int x,int f) { 39 vis[x] = 1; 40 for(int i = head[x];~i;i = nxt[i]) { 41 int sn = mo[i]; 42 if(sn == f) continue; 43 if(!vis[sn]) dfs(sn,x); 44 else { 45 rt1 = x,rt2 = sn; 46 Cntline = i; 47 } 48 } 49 } 50 51 int v[N]; 52 ll dp[N][2]; 53 void Dp(int x,int f) { 54 dp[x][0] = 0,dp[x][1] = v[x]; 55 for(int i = head[x];~i;i = nxt[i]) { 56 int sn = mo[i]; 57 if(sn == f) continue; 58 if(i == Cntline || ((i ^ 1) == Cntline)) continue; 59 // printf("%d->%d\n",x,sn); 60 Dp(sn,x); 61 dp[x][0] += max(dp[sn][0],dp[sn][1]); 62 dp[x][1] += dp[sn][0]; 63 } 64 } 65 66 int main() { 67 ms(head,-1); 68 n = read(); 69 rep(i,1,n) { 70 v[i] = read(); 71 add(i,read()); 72 } 73 ll ans = 0,maxx; 74 rep(i,1,n) { 75 maxx = 0; 76 if(vis[i]) continue; 77 rt1 = rt2 = Cntline = -2; 78 dfs(i,-1); 79 // printf("%d %d %d\n",rt1,rt2,Cntline); 80 Dp(rt1,rt1),maxx = dp[rt1][0]; 81 // printf("#%d\n",maxx); 82 Dp(rt2,rt2),maxx = max(maxx,dp[rt2][0]); 83 // printf("#%d\n",maxx); 84 ans += maxx; 85 } 86 printf("%lld\n",ans); 87 return 0; 88 }
View Code