HDU 4679 Terrorist’s destroy【Tree】
2013-08-15 19:23
351 查看
给一棵树,每条边上都有一个权值,去掉树上任意一条边之后,分成两个子树,两个子树的最长路与这条边上的权值相乘,的到一个乘积。问去掉那一条边可以使这个乘积最小。
首先找到树上的最长路,那么删边的时候有两种情况:
1. 这条边不是最长路上的边
2. 这条边是最长路上的边
对于第一种情况,很容易计算出乘积。
对于第二种情况,只需要计算出被分成的两个子树里面的最长路径长度即可,这个可以预处理一下。分析可以发现,这种情况下,两棵子树的最长路,一定是以整棵树的最长路的两个端点为起始点的,因此只需要预处理出所有点到两个端点的距离,然后根据删除的最长路边求两颗子树中的最大值即可。
所有预处理都是dfs……
首先找到树上的最长路,那么删边的时候有两种情况:
1. 这条边不是最长路上的边
2. 这条边是最长路上的边
对于第一种情况,很容易计算出乘积。
对于第二种情况,只需要计算出被分成的两个子树里面的最长路径长度即可,这个可以预处理一下。分析可以发现,这种情况下,两棵子树的最长路,一定是以整棵树的最长路的两个端点为起始点的,因此只需要预处理出所有点到两个端点的距离,然后根据删除的最长路边求两颗子树中的最大值即可。
所有预处理都是dfs……
#include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; #define N 100010 #define inf 0x7fffffff bool y ; int n, s, t, ds , dt , ms , mt , len, id, ans; struct node { int v, w, id; node() {} node(int _v, int _w, int _id) : v(_v), w(_w), id(_id) {} }; vector<node> g ; void dfs(int now, int fa) { int u; for (int i=0; i<g[now].size(); i++) if ((u = g[now][i].v) != fa) { ds[u] = ds[now] + 1; dfs(u, now); } } void dfs2(int now, int fa) { int u; for (int i=0; i<g[now].size(); i++) if ((u = g[now][i].v) != fa) { dt[u] = dt[now] + 1; dfs2(u, now); } } void d1(int now, int fa) { int u; mt[now] = dt[now]; for (int i=0; i<g[now].size(); i++) if ((u = g[now][i].v) != fa) { d1(u, now); mt[now] = max(mt[now], mt[u]); } } void d2(int now, int fa) { int u; ms[now] = ds[now]; for (int i=0; i<g[now].size(); i++) if ((u = g[now][i].v) != fa) { d2(u, now); ms[now] = max(ms[now], ms[u]); } } void work(int now, int fa) { int u, w; for (int i=0; i<g[now].size(); i++) if ((u = g[now][i].v) != fa) { if (ds[now] + 1 + dt[u] == len) w = g[now][i].w * max(ms[now], mt[u]); else w = g[now][i].w * len; if (w < ans) { ans = w, id = g[now][i].id; } else if (w == ans && g[now][i].id < id) id = g[now][i].id; work(u, now); } } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int size = 20 << 20; // 20MB char *p = (char*)malloc(size) + size; __asm__("movl %0, %%esp\n" :: "r"(p)); int T; scanf("%d", &T); for (int cas=1; cas<=T; cas++) { scanf("%d", &n); for (int i=0; i<=n; i++) { g[i].clear(); y[i] = false; } for (int i=1, a, b, c; i<n; i++) { scanf("%d%d%d", &a, &b, &c); g[a].push_back(node(b, c, i)); g[b].push_back(node(a, c, i)); } ds[1] = 0; dfs(1, 0); ds[s=0] = 0; for (int i=1; i<=n; i++) if (ds[i] > ds[s]) s = i; ds[s] = 0; dfs(s, 0); t = 0; for (int i=1; i<=n; i++) if (ds[i] > ds[t]) t = i; len = ds[t]; dt[t] = 0; dfs2(t, 0); d1(s, 0); d2(t, 0); id = ans = inf; work(s, 0); printf("Case #%d: %d\n", cas, id); } return 0; }
相关文章推荐
- 2013多校联合8 1004 Terrorist’s destroy(hdu 4679)
- HDU 4679 Terrorist’s destroy (树形DP)
- hdu 4679 Terrorist’s destroy 树的直径+dp
- hdu 4679 Terrorist’s destroy 树形dp水题 (2013多校联合)
- HDU 4679 Terrorist’s destroy (2013多校8 1004题 树形DP)
- HDU 4679 Terrorist’s destroy 解题报告
- hdu 4679 Terrorist’s destroy
- hdu-4679-Terrorist’s destroy
- HDU-4679 Terrorist’s destroy 树形DP,维护
- hdu 4679 Terrorist’s destroy (树形dp)
- hdu 4679 Terrorist’s destroy 树形DP
- hdu 4679 Terrorist’s destroy(树形dp)
- HDU 4679 Terrorist’s destroy
- hdu 4679 Terrorist’s destroy(树形DP)
- HDU 4679 Terrorist’s destroy (树形DP)
- hdu 4679 Terrorist’s destroy 多校第八场
- 【解题报告】HDU 4679 Terrorist’s destroy -- 树形dp 删一边求两子树直径
- HDU 4679 Terrorist’s destroy(树形dp | 多校8)
- hdu-4679-Terrorist’s destroy
- HDU 4679 Terrorist’s destroy