SPOJ 1825 Free Tour | 终极之树分治
求树上最长路径使得经过的拥挤节点个数不超过K
//欢迎访问这个博客!http://www.cnblogs.com/luyouqi233/p/8036828.html #include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#define N 200010
using namespace std;
typedef long long ll;
typedef pair<int,int>pii;
int head[N],ecnt,dis[N],fa[N],son[N],sze[N],ans,n,m,k,que[N],t[N],nump[N],maxn[N];
//dis[i] i到根节点的距离,fa[i] 父亲,son[i] i的最大子树大小,sze[i] BFS时以i为根的子树大小(son[]和sze[])用来求重心
//t[i] 当前子树节点到子树根且经过至多i个黑点的路径的最大权值和
//nump[i] 统计i到根节点的路径上的黑点数
//maxn[i] 以根节点为起点,终点在前面已经搜过的子树中,且该路径至多经过i个黑点,这样的路径的最大权值和。
bool vis[N],iscrowd[N];//iscrowd[i] 是否是拥挤节点
inline int read()
{
int ret=0,neg=1;
char j=getchar();
for (;j>'9' || j<'0';j=getchar())
if (j=='-') neg=-1;
for (;j>='0' && j<='9';j=getchar())
ret=ret*10+j-'0';
return ret*neg;
}
struct edge
{
int nxt,v,w;
}e[2*N];
vector <pair<int,int> > s;
void add(int u,int v,int w)
{
e[++ecnt].v=v,e[ecnt].w=w,e[ecnt].nxt=head[u],head[u]=ecnt;
e[++ecnt].v=u,e[ecnt].w=w,e[ecnt].nxt=head[v],head[v]=ecnt;
}
int calcG(int sv)
{
int u,v,mx=n,G,qn;
que[qn=1]=sv,fa[sv]=0;
for (int ql=1;ql<=qn;ql++)
{
sze[u=que[ql]]=1,son[u]=0;
for (int i=head[u];i;i=e[i].nxt)
{
if (vis[v=e[i].v] || v==fa[u]) continue;
fa[v]=u,que[++qn]=v;
}
}
for (int ql=qn;ql>=1;ql--)
{
u=que[ql],v=fa[u];
if (qn-sze[u]>son[u]) son[u]=qn-sze[u];
if (son[u]<mx) G=u,mx=son[u];
if (!v) break;
sze[v]+=sze[u];
if (sze[u]>son[v]) son[v]=sze[u];
}
return G;
}
inline int getmaxp(int st,ll L)
{
int qn=0,maxp=0;
que[++qn]=st;
nump[st]=iscrowd[st];
dis[st]=L;
fa[st]=0;
maxp=max(maxp,nump[st]);
for (int ql=1,u;ql<=qn;ql++)
for (int i=head[u=que[ql]],v;i;i=e[i].nxt)
{
if (vis[v=e[i].v] || v==fa[u]) continue;
fa[v]=u;
dis[v]=dis[u]+e[i].w;
nump[v]=nump[u]+iscrowd[v];
maxp=max(maxp,nump[v]);
que[++qn]=v;
}
return maxp;
}
inline void getmaxt(int st)
{
int qn=0;
que[++qn]=st;
t[nump[st]]=max(t[nump[st]],dis[st]);
for (int ql=1,u;ql<=qn;ql++)
for (int i=head[u=que[ql]],v;i;i=e[i].nxt)
{
if (vis[v=e[i].v] || v==fa[u]) continue;
t[nump[v]]=max(t[nump[v]],dis[v]);
que[++qn]=v;
}
return ;
}
void solve(int x)
{
int G=calcG(x);
vis[G]=1;s.clear();
for (int i=head[G],v;i;i=e[i].nxt)
if (!vis[v=e[i].v])
s.push_back(pii(getmaxp(v,e[i].w),v));
sort(s.begin(),s.end());
if (iscrowd[G]) k--;
for (int i=0;i<s.size();i++)
{
getmaxt(s[i].second);
int now=0;
if (i)
{
for (int j=s[i].first;j>=0;j--)
{
while (now+j<k && now<s[i-1].first)
now++,maxn[now]=max(maxn[now],maxn[now-1]);
if(now+j<=k)ans=max(ans,maxn[now]+t[j]);
}
}
if (i!=s.size()-1)
for (int j=0;j<=s[i].first;j++)
maxn[j]=max(maxn[j],t[j]),t[j]=0;
else
for (int j=0;j<=s[i].first;j++)
{
if (j<=k)
ans=max(ans,max(t[j],maxn[j]));
maxn[j]=t[j]=0;
}
}
if (iscrowd[G]) k++;
for (int i=head[G],v;i;i=e[i].nxt)
if (!vis[v=e[i].v])
solve(v);
return ;
}
int main()
{
scanf("%d%d%d",&n,&k,&m);
for (int i=1,x;i<=m;i++)
iscrowd[read()]=1;
for (int i=1,x,y,z;i<n;i++)
x=read(),y=read(),z=read(),add(x,y,z);
solve(1);
printf("%d",ans);
return 0;
}
SPOJ 1825 Free Tour | 终极之树分治的更多相关文章
- SPOJ 1825 Free tour II (树的点分治)
题目链接 Free tour II 题意:有$N$个顶点的树,节点间有权值, 节点分为黑点和白点. 找一条最长路径使得 路径上黑点数量不超过K个 这是树的点分治比较基本的题,涉及树上启发式合并……仰望 ...
- 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 II 树分治
题意: 给出一颗边带权的数,树上的点有黑色和白色.求一条长度最大且黑色节点不超过k个的最长路径,输出最长的长度. 分析: 说一下题目的坑点: 定义递归函数的前面要加inline,否则会RE.不知道这是 ...
- 【SPOJ】1825. Free tour II(点分治)
http://www.spoj.com/problems/FTOUR2/ 先前看了一会题解就自己yy出来了...对拍过后交tle.................. 自己造了下大数据........t ...
- 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 ...
- 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分
树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...
- hdu-5977 Garden of Eden(树分治)
题目链接: Garden of Eden Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/ ...
- 【BZOJ-1468】Tree 树分治
1468: Tree Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1025 Solved: 534[Submit][Status][Discuss] ...
随机推荐
- spring-mybatis整合异常
Failed to read artifact descriptor for XXXXXX:jar:XXXX.RELEAS 原因是maven的本地仓库没有设置好.在别处拷贝过来的项目会有自己的仓库位置 ...
- 网页更换主题以及绘制图形js代码实现
HTML代码实现: <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...
- SSH 登录时出现如下错误:No supported key exchange algorithms
https://help.aliyun.com/knowledge_detail/41486.html
- Mysql: pt-table-checksum 和 pt-table-sync 检查主从一致性,实验过程
一.安装 percona 包 1.安装仓库的包 https://www.percona.com/doc/percona-repo-config/yum-repo.html sudo yum insta ...
- html之table&select不为人知的操作
table标签和其它标签不一样,他有属性和方法! table属性: rows 可以得到table的row集合 cells 得到table所有单元格 table方法: insertR ...
- CentOS7 配置环境
1.安装CentOS 配置环境 (1)虚拟机中安装CentOS,进入系统使用yum命令不止正常执行…… 原因: 需要设置网卡激活 解决方法: vi /etc/sysconfig/network-scr ...
- JZOJ| 5910. DuLiu
Description LF是毒瘤出题人中AK IOI2019,不屑于参加NOI的唯一的人.他对人说话,总是满口垃圾题目者也,教人半懂不懂的.因为他姓李,别人便从QQ群上的“毒瘤李F ...
- 学习python第十二天,函数4 生成器generator和迭代器Iterator
在Python中,这种一边循环一边计算的机制,称为生成器:generator 要创建一个generator,有很多种方法.第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个genera ...
- 状压DP详解(位运算)
前言: 状压DP是一种非常暴力的做法(有一些可以排除某些状态的除外),例如dp[S][v]中,S可以代表已经访问过的顶点的集合,v可以代表当前所在的顶点为v.S代表的就是一种状态(二进制表示),比如 ...
- Android面试收集录8 HandlerThread详解
1.前言 我们知道在Android系统中,我们执行完耗时操作都要另外开启子线程来执行,执行完线程以后线程会自动销毁. 想象一下如果我们在项目中经常要执行耗时操作,如果经常要开启线程,接着又销毁线程, ...