UVALive 6900 Road Repair(点分治)
2015-12-18 03:06
423 查看
题意:
给定N≤2×104的一棵树,给定描述这棵树的四元组,(u,v,cost,profit),cost,profit≤103
对于树的所有简单路,找到一条简单路满足∑cost≤C≤2×107,且∑profit最大
求这个最大的∑profit
分析:
首先O(n2)暴力肯定要挂,dp背包的话显然C太大不行
我们需要一个带log的算法,考虑点分治
这题与POJ 1741 Tree很像,对于我们枚举的一条到重心的路径,假设这条路径的信息为(c,p)
此时我们需要知道当前子问题中其它到重心的路径(c′,p′)的max{p′},c′≤C−c,如何快速知道这个,可以考虑线段树或者BIT来维护最大值
那么ans=max{p+p′}
−−memset初始化BIT会T,正常回溯即可
代码:
给定N≤2×104的一棵树,给定描述这棵树的四元组,(u,v,cost,profit),cost,profit≤103
对于树的所有简单路,找到一条简单路满足∑cost≤C≤2×107,且∑profit最大
求这个最大的∑profit
分析:
首先O(n2)暴力肯定要挂,dp背包的话显然C太大不行
我们需要一个带log的算法,考虑点分治
这题与POJ 1741 Tree很像,对于我们枚举的一条到重心的路径,假设这条路径的信息为(c,p)
此时我们需要知道当前子问题中其它到重心的路径(c′,p′)的max{p′},c′≤C−c,如何快速知道这个,可以考虑线段树或者BIT来维护最大值
那么ans=max{p+p′}
−−memset初始化BIT会T,正常回溯即可
代码:
// // Created by TaoSama on 2015-12-18 // Copyright (c) 2015 TaoSama. All rights reserved. // //#pragma comment(linker, "/STACK:1024000000,1024000000") #include <algorithm> #include <cctype> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iomanip> #include <iostream> #include <map> #include <queue> #include <string> #include <set> #include <vector> using namespace std; #define pr(x) cout << #x << " = " << x << " " #define prln(x) cout << #x << " = " << x << endl const int N = 2e4 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7; const int M = 2e7 + 10; int n, C, ans; void getMax(int &x, int y) {x = max(x, y);} struct BIT { int mx[M]; void del(int i) { for(; i < M; i += i & -i) mx[i] = 0; } void update(int i, int v) { for(; i < M; i += i & -i) getMax(mx[i], v); } int query(int i) { int ret = 0; for(; i; i -= i & -i) getMax(ret, mx[i]); return ret; } } bit; struct Edge { int v, nxt, c, b; } edge[N << 1]; int head , cnt; void addEdge(int u, int v, int c, int b) { edge[cnt] = (Edge) {v, head[u], c, b}; head[u] = cnt++; edge[cnt] = (Edge) {u, head[v], c, b}; head[v] = cnt++; } bool vis ; int sz , mx , centroid; int getAll(int u, int f) { int ret = 1; for(int i = head[u]; ~i; i = edge[i].nxt) { int v = edge[i].v; if(v == f || vis[v]) continue; ret += getAll(v, u); } return ret; } void getCentroid(int u, int f, int all) { sz[u] = 1; mx[u] = 0; for(int i = head[u]; ~i; i = edge[i].nxt) { int v = edge[i].v; if(v == f || vis[v]) continue; getCentroid(v, u, all); sz[u] += sz[v]; getMax(mx[u], sz[v]); } getMax(mx[u], all - sz[u]); if(!centroid || mx[u] < mx[centroid]) centroid = u; } typedef pair<int, int> P; void getPath(int u, int f, int cost, int profit, vector<P>& path) { if(cost > C) return; path.push_back(P(cost, profit)); for(int i = head[u]; ~i; i = edge[i].nxt) { int v = edge[i].v; if(v == f || vis[v]) continue; getPath(v, u, cost + edge[i].c, profit + edge[i].b, path); } } void solve(int u) { centroid = 0; getCentroid(u, -1, getAll(u, -1)); int s = centroid; vis[s] = true; for(int i = head[s]; ~i; i = edge[i].nxt) { int v = edge[i].v; if(vis[v]) continue; solve(v); } vector<P> dummy; for(int i = head[s]; ~i; i = edge[i].nxt) { int v = edge[i].v; if(vis[v]) continue; vector<P> path; getPath(v, s, edge[i].c, edge[i].b, path); for(P &p : path) getMax(ans, p.second + bit.query(C - p.first)); for(P &p : path) bit.update(p.first, p.second); dummy.insert(dummy.end(), path.begin(), path.end()); } for(P &p : dummy) bit.del(p.first); vis[s] = false; } int main() { #ifdef LOCAL freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin); // freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout); #endif ios_base::sync_with_stdio(0); int t; scanf("%d", &t); while(t--) { cnt = 0; memset(head, -1, sizeof head); scanf("%d", &n); for(int i = 1; i < n; ++i) { int u, v, c, b; scanf("%d%d%d%d", &u, &v, &c, &b); addEdge(u, v, c, b); } scanf("%d", &C); ans = 0; solve(1); printf("%d\n", ans); } return 0; }
相关文章推荐
- bzoj-1095 Hide 捉迷藏
- hdu-5571 tree
- 【BZOJ2051】A Problem For Fun
- spoj1825 Free tour II 点分治
- POJ1741Tree(树上点分治)
- hdu5593 树形dp
- POJ 1987 Distance Statistics (树上点分治)
- POJ 1741 Tree(点分治)
- POJ 1741 Tree (树分治之点分治)
- HDU 4812 D Tree (树分治之点分治)
- HDU 4871 Shortest-path tree (树分治之点分治 最短路径树问题)
- poj 2114 Boatherds 点分治
- 点分治专题——bzoj 1468 &bzoj 2152 题解
- POJ 1741 Tree + POJ 1987 Distance Statistics【树的点分治】
- BZOJ 1468: Tree
- POJ 2114 Boatherds
- poj 1741 点分治论文题
- poj 2114 点分治
- BZOJ 2152: 聪聪可可 点分治/树dp
- [bzoj 1758] [Wc2010]重建计划