AGC018D - Tree and Hamilton Path

题意

给出一个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 }

 

转载于:https://www.cnblogs.com/ichn/p/7492301.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值