BZOJ 2599 [IOI2011]Race【Tree,点分治】
2013-08-16 18:47
357 查看
给出N(1 <= N <= 200000)个结点的树,求长度等于K(1 <= K <= 1000000)的路径的最小边数。
点分治,这道题目和POJ 2114很接近,2114是求是否存在长度为K的边,但是那个K比较大。但是这道题目的K比之小了10倍。
1. 用V[i]表示到当前树根root的路径长度为i 时的点(赋值为root结点即可),这样就可以用来判断两条到根的路径长度之和是否等于K:
结点a的root的距离为i,结点b到root的距离为j,处理完a之后会得到V[i] = root,那么在处理结点b的时候,如果V[K-j] = root,就说明某一个a和b的路径长度为K,此时,就可以更新最小边数了。
2. e[i]表示到当前树根root的路径长度为i 时的边的最小条数。
点分治,这道题目和POJ 2114很接近,2114是求是否存在长度为K的边,但是那个K比较大。但是这道题目的K比之小了10倍。
1. 用V[i]表示到当前树根root的路径长度为i 时的点(赋值为root结点即可),这样就可以用来判断两条到根的路径长度之和是否等于K:
结点a的root的距离为i,结点b到root的距离为j,处理完a之后会得到V[i] = root,那么在处理结点b的时候,如果V[K-j] = root,就说明某一个a和b的路径长度为K,此时,就可以更新最小边数了。
2. e[i]表示到当前树根root的路径长度为i 时的边的最小条数。
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <iostream> using namespace std; #define N 200010 #define inf 0x3f3f3f3f struct node { int v, l; node() {} node(int _v, int _l): v(_v), l(_l) {}; }; vector<node> g ; int n, K, cur, root, size, ans; int s , f , d , e ; //s子树的结点数,f求重心,d子结点到根的距离,e子结点到根的边数 int v[N*10], c[N*10]; bool done ; void getroot(int now, int fa) { int u; s[now] = 1, f[now] = 0; for (int i=0; i<g[now].size(); i++) if ((u = g[now][i].v) != fa && !done[u]) { getroot(u, now); s[now] += s[u]; f[now] = max(f[now], s[u]); } f[now] = max(f[now], size-s[now]); if (f[now] < f[root]) root = now; } void dfs1(int now, int fa) { if (d[now] > K) return ; if (v[K-d[now]] == cur) ans = min(ans, c[K-d[now]]+e[now]); int u; for (int i=0; i<g[now].size(); i++) if ((u = g[now][i].v) != fa && !done[u]) { d[u] = d[now] + g[now][i].l; e[u] = e[now] + 1; dfs1(u, now); } } void dfs2(int now, int fa) { if (d[now] > K) return ; if (v[d[now]] != cur) { c[d[now]] = e[now]; v[d[now]] = cur; } else c[d[now]] = min(c[d[now]], e[now]); int u; for (int i=0; i<g[now].size(); i++) if ((u = g[now][i].v) != fa && !done[u]) dfs2(u, now); } void work(int now) { v[0] = cur = now + 1; int u; for (int i=0; i<g[now].size(); i++) if (!done[u = g[now][i].v]) { d[u] = g[now][i].l; e[u] = 1; dfs1(u, now); dfs2(u, now); } getroot(now, n); //更新s数组 done[now] = true; for (int i=0; i<g[now].size(); i++) if (!done[u = g[now][i].v]) { f = size = s[u]; getroot(u, root=n); work(root); } } int main() { scanf("%d%d", &n, &K); for (int i=0; i<=n; i++) g[i].clear(); for (int i=1, a, b, c; i<n; i++) { scanf("%d%d%d", &a, &b, &c); g[a].push_back(node(b, c)); g[b].push_back(node(a, c)); } memset(done, false, sizeof(done)); ans = f = size = n; getroot(0, root=n); work(root); printf("%d\n", ans < n ? ans : -1); return 0; }
相关文章推荐
- BZOJ 2599 [IOI2011]Race【Tree,点分治】
- BZOJ2599 [IOI2011]Race 【点分治】
- BZOJ 2599: [IOI2011]Race 点分治题解
- 【点分治】BZOJ 2599:[IOI2011]Race
- [BZOJ2599][IOI2011]Race(点分治)
- BZOJ2599 [IOI2011]Race 【点分治】
- [BZOJ2599][IOI2011]Race-树上启发式合并(dsu on tree)
- BZOJ 2599: [IOI2011]Race [点分治]
- 【BZOJ 2599】【IOI 2011】Race 点分治
- 【bzoj2599】[IOI2011]Race 树的点分治
- BZOJ 2599 IOI 2011 Race 树的分治
- 点分治[BZOJ]2599: [IOI2011]Race
- [bzoj2599][IOI2011]Race_树上点分治
- Bzoj2599:[IOI2011]Race:树的点分治
- bzoj2599: [IOI2011]Race 点分治
- [BZOJ2599][IOI2011]Race 点分治
- bzoj2599 [IOI2011]Race(点分治)
- 【BZOJ2599】[IOI2011]Race【点分治】
- 【BZOJ】2599 [IOI2011]Race 点分治
- BZOJ2599 [IOI2011]Race 点分治