SPOJ 1825 Free tour II 解题报告(树分治)
来源:互联网 发布:詹姆斯2016季后赛数据 编辑:程序博客网 时间:2024/05/20 07:49
1825. Free tour II
Problem code: FTOUR2
After the success of 2nd anniversary (take a look at problem FTOUR for more details), this 3rd year, Travel Agent SPOJ goes on with another discount tour.
The tour will be held on ICPC island, a miraculous one on the Pacific Ocean. We list N places (indexed from 1 to N) where the visitors can have a trip. Each road connecting them has an interest value, and this value can be negative(if there is nothing interesting to view there). Simply, these N places along with the roads connecting them form atree structure. We will choose two places as the departure and destination of the tour.
Since September is the festival season of local inhabitants, some places are extremely crowded (we call themcrowded places). Therefore, the organizer of the excursion hopes the tour will visit at most K crowded places (too tiring to visit many of them) and of course, the total number of interesting value should be maximum.
Briefly, you are given a map of N places, an integer K, and M id numbers of crowded place. Please help us to find the optimal tour. Note that we can visit each place only once (or our customers easily feel bored), also the departure and destination places don't need to be different.
Input
There is exactly one case. First one line, containing 3 integers N K M, with 1 <= N <= 200000, 0 <= K <= M, 0 <=M <= N.
Next M lines, each line includes an id number of a crowded place.
The last (N - 1) lines describe (N - 1) two-way roads connected N places, form a b i, with a, b is the id of 2 places, and i is its interest value (-10000 <= i <= 10000).
Output
Only one number, the maximum total interest value we can obtain.
Example
Input:8 2 33571 3 12 3 103 4 -24 5 -15 7 65 6 54 8 3Output:12
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#include <queue>#include <vector>#include <map>#include <set>#include <string>#include <iomanip>#include <cassert>using namespace std;#pragma comment(linker, "/STACK:1024000000,1024000000")#define ff(i, n) for(int i=0;i<(n);i++)#define fff(i, n, m) for(int i=(n);i<=(m);i++)#define dff(i, n, m) for(int i=(n);i>=(m);i--)#define travel(e, u) for(int e = u, v = vv[u]; e; e = nxt[e], v = vv[e])#define Bit(n) (1LL<<(n))#define And(a, b) ((a) & (b))#define Xor(a, b) ((a) ^ (b))#define Or(a, b) ((a) | (b))typedef long long LL;typedef unsigned long long ULL;void work();int main(){#ifdef ACM freopen("in.txt", "r", stdin);#endif // ACM work();}void scanf(int & x, char c = 0){ while((c = getchar()) < '0' || c > '9'); x = c - '0'; while((c = getchar()) >= '0' && c <= '9') x = x * 10 + (c - '0');}#define rep(i,a,b) for(int i = (a);i<(b);++i)#define rrep(i,a,b) for(int i = (a);i>=(b);--i)#define clr(a,x) memset(a,x,sizeof(a))/*****************************************华丽分割线**********************************************/const int maxv = 222222;/// Globalint n, m, k;int ans;/// Edgeint edge[maxv], ecnt;int nxt[maxv * 2], vv[maxv * 2], ww[maxv * 2];/// Treebool blk[maxv], vis[maxv];int siz[maxv], mon[maxv], dad[maxv];int root, minN, maxD;/// Tree Nodeint all[maxv], allK;int now[maxv], nowK;struct Node{ int v, w, d; Node(int v = 0, int w = 0, int d = 0) : v(v), w(w), d(d) {} bool operator<(const Node & cmp) const { return d < cmp.d; }};void init(){ /// Edge initial clr(edge, 0); ecnt = 2; /// Ans Initial ans = 0; /// Tree Initial clr(blk, 0); clr(vis, 0);}void addEdge(int u, int v, int w, int first[]){ nxt[ecnt] = first[u], vv[ecnt] = v, ww[ecnt] = w, first[u] = ecnt++;}void input(){ ff(i, m) { int u; scanf("%d", &u); blk[u] = true; } ff(i, n-1) { int u, v, w; scanf("%d%d%d", &u, &v, &w); addEdge(u, v, w, edge); addEdge(v, u, w, edge); }}void dfsSize(int u){ siz[u] = 1; mon[u] = 0; travel(e, edge[u]) if(!vis[v] && v != dad[u]) dad[v] = u, dfsSize(v), siz[u] += siz[v], mon[u] = max(mon[u], siz[v]);}int r;void dfsRoot(int u){ mon[u] = max(mon[u], siz[r] - siz[u]); if(mon[u] < minN) minN = mon[u], root = u; travel(e, edge[u]) if(!vis[v] && v != dad[u]) dfsRoot(v);}int bb;void dfsDeep(int u){ if(blk[u]) bb++; maxD = max(maxD, bb); travel(e, edge[u]) if(!vis[v] && v != dad[u]) dad[v] = u, dfsDeep(v); if(blk[u]) bb--;}int wv;void dfsValue(int u){ if(blk[u]) bb++; now[bb] = max(now[bb], wv); travel(e, edge[u]) if(!vis[v] && v != dad[u]) wv += ww[e], dfsValue(v), wv -= ww[e]; if(blk[u]) bb--;}void dfs(int u){ /// Get root dad[u] = 0, dfsSize(u); r = u, minN = n, dfsRoot(u); /// Get son and sort u = root; vector<Node> son; travel(e, edge[u]) if(!vis[v]) bb = 0, dad[v] = u, maxD = 0, dfsDeep(v), son.push_back(Node(v, ww[e], maxD)); sort(son.begin(), son.end()); if(son.size() == 0) return; allK = -1; int kk = k; if(blk[u]) kk--; if(kk >= 0) ff(i, son.size()) { nowK = son[i].d; fff(j, 0, nowK) now[j] = Bit(31); bb = 0; wv = son[i].w; dfsValue(son[i].v); fff(j, 1, nowK) now[j] = max(now[j], now[j-1]); ans = max(ans, now[min(kk, nowK)]); if(allK == -1) { } else if(allK < kk) { if(allK + nowK <= kk) ans = max(ans, now[nowK] + all[allK]); else fff(j, max(0, kk-nowK), allK) ans = max(ans, all[j] + now[kk-j]); } else { dff(j, kk, 0) ans = max(ans, all[j] + now[kk-j]); } /// Merge fff(j, 0, allK) all[j] = max(all[j], now[j]); if(allK >= 0) all[0] = max(all[0], now[0]); fff(j, max(allK, 0) + 1, nowK) all[j] = max(now[j], all[j-1]); allK = nowK; } vis[u] = true; travel(e, edge[u]) if(!vis[v]) dfs(v);}void work(){ while(scanf("%d%d%d", &n, &k, &m) == 3) { init(); input(); dfs(1); printf("%d\n", ans); }}
- SPOJ 1825 Free tour II 解题报告(树分治)
- Spoj - 1825 Free tour II(树的点分治)
- spoj 1825 Free tour II 点分治
- 【SPOJ】1825 Free tour II 点分治
- spoj 1825 Free tour II(树的点分治)
- spoj 1825 Free tour II(树分治+启发式合并)
- SPOJ 1825 FTOUR2 - Free tour II (树上点分治)
- SPOJ Free tour II 点分治
- SPOJ 1825 Free tour II
- 【spoj 1825】Free tour II
- 树分治点分治(spoj1825 Free tour II)
- SPOJ FTOUR2 Free tour II
- Spoj FTOUR Free Tour II
- 【数据结构&图论】SPOJ Free tour II
- SPOJ 1825 Free Tour 2
- spoj1825 Free tour II 点分治
- HDOJ-1224-Free DIY Tour 解题报告
- SPOJFTOUR2-Free tour II
- Zabbix Python API 应用实战
- Android Json解析课程
- Java实现冒泡排序以及优化冒泡排序的一些小技巧
- Windows8.1驱动编写以及内核调试(一) 做好准备工作并编写第一个驱动程序
- 请问学习的方向在哪里
- SPOJ 1825 Free tour II 解题报告(树分治)
- NSDictionary一些常用用法
- C中和C++中static的作用?
- hdu1561 树形dp
- OpenCV Haar AdaBoost源码改进(比EMCV快6倍)
- argv是一个指针
- Python 中对文本框内容是否为非负整数的检判别
- 排序
- Linux下MySQL定时备分脚本