1. 程式人生 > >AGC018D - Tree and Hamilton Path

AGC018D - Tree and Hamilton Path

!= 兩個 getch ace 完全 ade for con urn

題意

給出一個n個點的帶邊權的樹,再給出一個n個點的完全圖,其中每兩個點之間的距離為這兩個點在樹上的距離,求最大的哈密頓圖。

做法

直接考慮在樹上的遊歷,如果存在一條邊把樹分成大小相同的兩半,然後在兩半中的點中交替走,這樣子顯然是最優的,因為每條邊都會達到可能的最多的訪問次數;否則必然存在一個點(重心),去除這個點之後的森林裏每棵樹的大小都不大於n/2,這樣最優的遊歷一定是從每棵樹出來走到另一棵中沒走過的點,這樣的安排總是存在的。考慮到最後並不會再訪問重心,取重心連出去的權值最小的一條邊來承擔這個代價。

這種題就考慮到最優情況仔細分析就好了.

  1 #include <bits/stdc++.h>
  2
using namespace std; 3 namespace my_header { 4 #define pb push_back 5 #define mp make_pair 6 #define pir pair<int, int> 7 #define vec vector<int> 8 #define pc putchar 9 #define clr(t) memset(t, 0, sizeof t) 10 #define pse(t, v) memset(t, v, sizeof t) 11 #define bl puts("") 12
#define wn(x) wr(x), bl 13 #define ws(x) wr(x), pc(‘ ‘) 14 const int INF = 0x3f3f3f3f; 15 typedef long long LL; 16 typedef double DB; 17 inline char gchar() { 18 char ret = getchar(); 19 for(; (ret == \n || ret == \r || ret == ) && ret != EOF; ret = getchar());
20 return ret; } 21 template<class T> inline void fr(T &ret, char c = , int flg = 1) { 22 for(c = getchar(); (c < 0 || 9 < c) && c != -; c = getchar()); 23 if (c == -) { flg = -1; c = getchar(); } 24 for(ret = 0; 0 <= c && c <= 9; c = getchar()) 25 ret = ret * 10 + c - 0; 26 ret = ret * flg; } 27 inline int fr() { int t; fr(t); return t; } 28 template<class T> inline void fr(T&a, T&b) { fr(a), fr(b); } 29 template<class T> inline void fr(T&a, T&b, T&c) { fr(a), fr(b), fr(c); } 30 template<class T> inline char wr(T a, int b = 10, bool p = 1) { 31 return a < 0 ? pc(-), wr(-a, b, 0) : (a == 0 ? (p ? pc(0) : p) : 32 (wr(a/b, b, 0), pc(0 + a % b))); 33 } 34 template<class T> inline void wt(T a) { wn(a); } 35 template<class T> inline void wt(T a, T b) { ws(a), wn(b); } 36 template<class T> inline void wt(T a, T b, T c) { ws(a), ws(b), wn(c); } 37 template<class T> inline void wt(T a, T b, T c, T d) { ws(a), ws(b), ws(c), wn(d); } 38 template<class T> inline T gcd(T a, T b) { 39 return b == 0 ? a : gcd(b, a % b); } 40 template<class T> inline T fpw(T b, T i, T _m, T r = 1) { 41 for(; i; i >>= 1, b = b * b % _m) 42 if(i & 1) r = r * b % _m; 43 return r; } 44 }; 45 using namespace my_header; 46 47 const int N = 1e5 + 100; 48 const int M = N<<1; 49 50 struct Edge { 51 int e, h[N], t[M], n[M], w[M]; 52 void init() { 53 e = 0; memset(h, -1, sizeof h); 54 } 55 void add(int u, int v, int c) { 56 t[e] = v, n[e] = h[u], w[e] = c, h[u] = e++; 57 t[e] = u, n[e] = h[v], w[e] = c, h[v] = e++; 58 } 59 } e; 60 61 int n; 62 LL ans; 63 64 int siz[N], ef[N]; 65 void dfs(int u, int f = -1) { 66 siz[u] = 1; 67 for (int i = e.h[u]; i != -1; i = e.n[i]) { 68 int v = e.t[i]; 69 if (v == f) continue; 70 ef[v] = i; 71 dfs(v, u); 72 siz[u] += siz[v]; 73 } 74 ans += 1LL * e.w[ef[u]] * min(siz[u], n - siz[u]) * 2; 75 } 76 77 78 int main() { 79 #ifdef lol 80 freopen("d.in", "r", stdin); 81 freopen("d.out", "w", stdout); 82 #endif 83 84 fr(n); 85 e.init(); 86 for (int i = 1; i < n; ++i) { 87 int u, v, w; 88 fr(u, v, w); 89 e.add(u, v, w); 90 } 91 dfs(1); 92 //for (int i = 1; i <= n; ++i) 93 // ws(siz[i]); 94 //puts(""); 95 for (int i = 2; i <= n; ++i) { 96 if (siz[i] * 2 == n) { 97 wt(ans - e.w[ef[i]]); 98 return 0; 99 } 100 } 101 int val = INT_MAX; 102 103 //wt(ans); 104 for (int i = 1; i <= n; ++i) { 105 int maxSiz = n - siz[i], minEdge = i == 1 ? INT_MAX : e.w[ef[i]]; 106 for (int j = e.h[i]; j != -1; j = e.n[j]) { 107 if (e.t[j] != e.t[ef[i] ^ 1]) { 108 maxSiz = max(maxSiz, siz[e.t[j]]); 109 minEdge = min(minEdge, e.w[j]); 110 } 111 } 112 //wt(maxSiz); 113 if (maxSiz * 2 <= n) { 114 val = min(val, minEdge); 115 } 116 } 117 wt(ans - val); 118 119 return 0; 120 }

AGC018D - Tree and Hamilton Path