【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 ...
随机推荐
- zoj3745 Salary Increasing
OJ Problem Set - 3745 Salary Increasing Time Limit: 2 Seconds Memory Limit: 65536 KB Edward has ...
- JS的trim()方法
去除字符串左右两端的空格,在vbscript里面可以轻松地使用 trim.ltrim 或 rtrim,但在js中却没有这3个内置方法,需要手工编写.下面的实现方法是用到了正则表达式,效率不错,并把这三 ...
- tcp/IP点对点通信程序
点对点的通信 服务器端与客户端在建立连接之后创建一个进程 服务器端: 子进程用于接收主机的输入并将数据发送出去.父进程用于接收客户端的数据并输出到主机. 子进程一直等待主机的输入,输入的数据放在发送缓 ...
- Java for LeetCode 069 Sqrt(x)
Implement int sqrt(int x). Compute and return the square root of x. 解题思路一: public int mySqrt(int x) ...
- MFC RadioButton
添加一组RadioButton 多个radio button,IDC_RADIO1,IDC_RADIO2,IDC_RADIO3 ..将IDC_RADIO1的Group属性选择上,其他不要选Group属 ...
- 小吃(codevs 3231)
3231 小吃 时间限制: 1 s 空间限制: 16000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description 这里简直是吃货的天堂,小吃太多了. ...
- Java编程设计2
一般我们会以这种设计方式生产对象实例,如: 创建一个接口: public interface TestOpen { String getVirtualHost(); String getCapabil ...
- Linux下创建ftp用户并锁定根目录
[root@d vsftpd]# vi /etc/vsftpd/chroot_list 加入要锁定根目录的ftp用户名(一行只能一个用户) [root@ vsftpd]# vi /etc/vsftpd ...
- laraver ajax分页
,设置分页容器参考laraver手册 我的设置代码如下: ,控制器调用的方法:代码如下 ); include($path); $content = ob_get_cle ...
- loj 1031(区间dp+记忆化搜索)
题目链接:http://lightoj.com/volume_showproblem.php?problem=1031 思路:dp[i][j]表示从区间i-j中能取得的最大值,然后就是枚举分割点了. ...