1. 程式人生 > >BZOJ1912 最長鏈樹形DP

BZOJ1912 最長鏈樹形DP

style add fin amp one sizeof signed sign oid

每次求出最長鏈更新答案後要將最長鏈上的邊權改為-1

寫的賊長 還可以優化...

技術分享圖片
  1 /*Huyyt*/
  2 #include<bits/stdc++.h>
  3 #define mem(a,b) memset(a,b,sizeof(a))
  4 #define pb push_back
  5 using namespace std;
  6 typedef long long ll;
  7 typedef unsigned long long ull;
  8 using namespace std;
  9 const int MAXN = 1e5 + 5, MAXM = 2e5 + 5
; 10 int to[MAXM << 1], nxt[MAXM << 1], Head[MAXN], ed = 1; 11 int value[MAXM << 1]; 12 inline void addedge(int u, int v, int val) 13 { 14 to[++ed] = v; 15 nxt[ed] = Head[u]; 16 value[ed] = val; 17 Head[u] = ed; 18 } 19 int d[MAXN]; 20 void dfs(int
x, int pre) 21 { 22 for (int v, i = Head[x]; i; i = nxt[i]) 23 { 24 v = to[i]; 25 if (v == pre) 26 { 27 continue; 28 } 29 d[v] = d[x] + value[i]; 30 dfs(v, x);
31 } 32 } 33 void change(int x) 34 { 35 for (int v, i = Head[x]; i; i = nxt[i]) 36 { 37 v = to[i]; 38 if (d[v] == d[x] - 1) 39 { 40 value[i] = value[i ^ 1] = -1; 41 change(v); 42 } 43 } 44 } 45 int s, t, dmx = -1; 46 int ans2 = 0, vis[MAXN], dpd[MAXN]; 47 void dp(int x) 48 { 49 vis[x] = 1; 50 for (int v, i = Head[x]; i; i = nxt[i]) 51 { 52 v = to[i]; 53 if (vis[v]) 54 { 55 continue; 56 } 57 dp(v); 58 ans2 = max(ans2, dpd[x] + dpd[v] + value[i]); 59 dpd[x] = max(dpd[x], dpd[v] + value[i]); 60 } 61 } 62 int main() 63 { 64 int anser; 65 int n, k; 66 int u, v; 67 scanf("%d %d", &n, &k); 68 for (int i = 1; i < n; i++) 69 { 70 scanf("%d %d", &u, &v); 71 addedge(u, v, 1), addedge(v, u, 1); 72 } 73 anser = 2 * (n - 1); 74 d[1] = 0; 75 dfs(1, 0); 76 for (int i = 1; i <= n; i++) 77 { 78 if (d[i] > dmx) 79 { 80 dmx = d[i]; 81 s = i; 82 } 83 } 84 d[s] = 0; 85 dfs(s, 0); 86 dmx = -1; 87 for (int i = 1; i <= n; i++) 88 { 89 if (d[i] > dmx) 90 { 91 dmx = d[i]; 92 t = i; 93 } 94 } 95 anser -= d[t] - 1; 96 if (k == 1) 97 { 98 printf("%d\n", anser); 99 return 0; 100 } 101 change(t); 102 dp(1); 103 anser -= ans2 - 1; 104 printf("%d\n", anser); 105 return 0; 106 }
//BZOJ1912

BZOJ1912 最長鏈樹形DP