【SPOJ】1825. Free tour II(点分治)
http://www.spoj.com/problems/FTOUR2/
先前看了一会题解就自己yy出来了。。。对拍过后交tle。。。。。。。。。。。。。。。。。。
自己造了下大数据。。。。。。。。tle。。。。。。。。。。。。。。。。。。。。。。。。。
what?
首先来看经过当前点的路径:
设g[x,i]表示第x个孩子能得到的路径上黑点最多有i个(注意是最多)的最大长度,因为遍历的节点最坏为n个(第一层),因此在每一层都是$O(n)$的,可以承受。
考虑转移答案
$$ans[x]=max\{g[u,i]+g[v,k-black[x]-i], u!=v\}$$
这个方程似乎很显然?如果看不懂的请仔细思考所定义的状态,特别是“最多为i个”
可是最坏情况下有$n$个黑点,所以状态数目就有$n^2$了(尽管在每一层中有效转移状态仅仅为$O(n)$),而且暴力转移也是$O(n^2)$
考虑减少状态,试着去掉第一维。发现如果有序遍历每个子女时,之前遍历过的可以直接查找,而且每一次都是同样的操作(即查找之前子女的每一个状态),而转移是max,想到合并为一个状态。那么状态只剩$O(n)$
但是发现,如果k达到了$n$,那么我们在更新g值的话(更新g值就是从小的黑点更新大的黑点,即g[i]=max{g[j], j<=i},会tle成狗。。。。因为每次都要更新到k。。。。)
就是到这里我交了tle。。。。。。。。。。。。。。。。。。然后想不出来了。。。。。。。。。。。。。。。。。
做法:发现如果子女遍历黑点的深度是递增的话,因为每次更新g值不超过当前黑点深度,所以所有更新g值次数加起来均摊$O(n)$
排序子女深度$O(nlgn)$,因此本题总时间复杂度为$O(nlg^2n)$
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << (#x) << " = " << (x) << endl
#define error(x) (!(x)?puts("error"):0)
#define rdm(x, i) for(int i=ihead[x]; i; i=e[i].next)
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; } const int N=200005, oo=~0u>>1;
int ihead[N], cnt, n;
struct dat { int next, to, w; }e[N<<1];
inline void add(int u, int v, int w) {
e[++cnt].next=ihead[u]; ihead[u]=cnt; e[cnt].to=v; e[cnt].w=w;
e[++cnt].next=ihead[v]; ihead[v]=cnt; e[cnt].to=u; e[cnt].w=w;
}
int root, sz[N], vis[N], ans, h[N], blc[N], g[N], bsz[N], K, mn;
void getroot(int x, int fa, int sum) {
sz[x]=1; int mx=0, y;
rdm(x, i) if(!vis[y=e[i].to] && e[i].to!=fa) {
getroot(y, x, sum);
sz[x]+=sz[y];
mx=max(mx, sz[y]);
}
mx=max(mx, sum-mx);
if(mx<mn) mn=mx, root=x;
}
void cal(int x, int len, int num, int fa) {
h[num]=max(h[num], len); int y;
rdm(x, i) if(!vis[y=e[i].to] && e[i].to!=fa) {
cal(y, len+e[i].w, num+blc[y], x);
}
}
void fix(int len) {
int mx=-oo;
for1(i, 0, len) {
mx=max(mx, g[i]);
g[i]=mx;
}
}
void getbsz(int x, int fa) {
bsz[x]=blc[x];
rdm(x, i) if(!vis[e[i].to] && e[i].to!=fa) getbsz(e[i].to, x), bsz[x]+=bsz[e[i].to];
}
struct QQ {
int dep, id;
bool operator<(const QQ &a) const { return dep<a.dep; }
}q[N];
void dfs(int x, int sum) {
vis[x]=1;
int y, maxdep=-1, kk=K-blc[x];
int tot=0, pos;
rdm(x, i) if(!vis[y=e[i].to]) {
getbsz(y, x);
q[++tot].dep=bsz[y];
q[tot].id=i;
}
sort(q+1, q+1+tot);
for1(i, 1, tot) {
int now=q[i].id, y=e[now].to, s=min(q[i].dep, kk);
for1(j, 0, s) h[j]=-oo;
cal(y, e[now].w, blc[y], x);
if(i==1) for1(j, 0, s) g[j]=h[j];
else {
for1(j, 0, s) {
pos=kk-j; if(pos>maxdep) pos=maxdep;
if(g[pos]!=-oo && h[j]!=-oo) ans=max(g[pos]+h[j], ans);
}
for1(j, 0, s) g[j]=max(g[j], h[j]);
}
maxdep=s;
fix(maxdep);
}
ans=max(ans, g[min(kk, maxdep)]);
rdm(x, i) if(!vis[y=e[i].to]) {
int s=sz[y]>sz[x]?sum-sz[x]:sz[y];
root=0; mn=oo; getroot(y, x, s);
dfs(root, s);
}
}
int main() {
read(n); read(K); int m=getint();
for1(i, 1, m) blc[getint()]=1;
rep(i, n-1) { int u=getint(), v=getint(), w=getint(); add(u, v, w); }
mn=oo;
getroot((n+1)>>1, -1, n);
dfs(root, n);
print(ans);
return 0;
}
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 a tree 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 them crowded 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 3
3
5
7
1 3 1
2 3 10
3 4 -2
4 5 -1
5 7 6
5 6 5
4 8 3 Output:
12
Explanation
【SPOJ】1825. Free tour II(点分治)的更多相关文章
- SPOJ 1825 Free tour II 树分治
题意: 给出一颗边带权的数,树上的点有黑色和白色.求一条长度最大且黑色节点不超过k个的最长路径,输出最长的长度. 分析: 说一下题目的坑点: 定义递归函数的前面要加inline,否则会RE.不知道这是 ...
- SPOJ 1825 Free tour II (树的点分治)
题目链接 Free tour II 题意:有$N$个顶点的树,节点间有权值, 节点分为黑点和白点. 找一条最长路径使得 路径上黑点数量不超过K个 这是树的点分治比较基本的题,涉及树上启发式合并……仰望 ...
- spoj 1825 Free tour II
http://www.spoj.com/problems/FTOUR2/ After the success of 2nd anniversary (take a look at problem FT ...
- [spoj] FTOUR2 FREE TOUR II || 树分治
原题 给出一颗有n个点的树,其中有M个点是拥挤的,请选出一条最多包含k个拥挤的点的路径使得经过的权值和最大. 正常树分治,每次处理路径,更新答案. 计算每棵子树的deep(本题以经过拥挤节点个数作为d ...
- SPOJ:Free tour II (树分治+启发式合并)
After the success of 2nd anniversary (take a look at problem FTOUR for more details), this 3rd year, ...
- SPOJ 1825 Free Tour | 终极之树分治
求树上最长路径使得经过的拥挤节点个数不超过K //欢迎访问这个博客!http://www.cnblogs.com/luyouqi233/p/8036828.html #include<cstdi ...
- SPOJ FTOUR2 - Free tour II
Description 有些黑点,问你选择不超过 \(k\) 个黑点的路径,路径权值最大是多少. Sol 点分治. 这是qzc的论文题,不过我感觉他的翻译好强啊...我还是选择了自己去看题目... 点 ...
- SP1825 FTOUR2 - Free tour II 点分治+启发式合并+未调完
题意翻译 给定一棵n个点的树,树上有m个黑点,求出一条路径,使得这条路径经过的黑点数小于等于k,且路径长度最大 Code: #include <bits/stdc++.h> using n ...
- 【SPOJ1825】Free tour II (点分治,启发式)
题意: 边权可能为负 思路: 感觉我自己写的还是太过僵硬了,可以灵活一点,比如可以多写几个不同的dfs求出不同的信息,而不是压到同一个dfs里 #include<cstdio> #incl ...
随机推荐
- Heap:Moo University - Financial Aid(POJ 2010)
牛的学校 题目大意:这只Bessie真是太顽皮了,她又搞了个学校,准备招生,准备通过一个考试筛选考生,但是不能招到每个学生,每个学生也不能一定能上学,要资助,问你在一定资金内,怎么收学生,使收到 ...
- Java问题排查工具箱[转载]
转载自:http://hellojava.info/?p=517 作者:阿里毕玄 问题排查除了最重要的解决思路和逻辑推导能力外,工具也是不可缺少的一部分,一个好用的工具可以事半功倍,甚至在某些情况下会 ...
- [Android Pro] RecyclerView实现瀑布流效果(二)
referece to : http://blog.csdn.net/u010687392 在上篇中我们知道RecyclerView中默认给我们提供了三种布局管理器,分别是LinearLayoutMa ...
- 解决Exception in thread "main" java.lang.UnsupportedClassVersionError: org/apache/maven/cli/MavenCli : Unsupported major.minor version 51.0
jdk问题 解决方案: 更换IDE的jdk
- cocos2dx创建sprite的多种方法
方法一 最常用,也是最简单的一种方法 CCSprite *bg=CCSprite::create(,,,)); bg->setAnchorPoint(ccp(,)); bg->setPos ...
- 用java程序打印菱形
代码如下
- mysql多实例(个人的情况,不是大众的)里面有配置好的脚本+主从复制
[root@DB-S ~]# ll /usr/local/|grep mysql lrwxrwxrwx. 1 root root 21 Jun 14 01:52 mysql -> /alidat ...
- 企业级项目中最常用到的SQL
用SQL语句添加删除修改字段 1.增加字段 alter table docdsp add dspcode char(200) 例如: 表gwamis.d410Sctzmx添加字段f410 ...
- 转载——用Mixer API函数调节控制面板的音频设置
关键词:Mixer函数,控制面板,音频设备调节 如果你用过windows的音频设备,比如播放音乐或者录音,聊天,调节麦克或者声音的大小,以及设置静音,都可以通过控制面板中的音频设置面板来调节,你对于下 ...
- android操作XML的几种方式(转)
XML作为一种业界公认的数据交换格式,在各个平台与语言之上,都有广泛使用和实现.其标准型,可靠性,安全性......毋庸置疑.在android平台上,我们要想实现数据存储和数据交换,经常会使用到xml ...