Luogu 4149 Race

  • 用点分治解决.
  • 点分治在计算路径贡献时,为了不统计在一颗子树中的路径,解决方法一种是容斥,但在这种求最值问题中不便用容斥来撤销.
  • 另一种则是,处理一颗子树时,只考虑前面的子树中产生的贡献,而将当前的子树的节点暂时存储在一个栈中,当前子树处理完毕后,再让栈中的点产生贡献,就可以解决求最值等容斥难以处理的问题.
  • 就本题而言,记 \(tmp[i]\) 表示路径长度为 \(i\) 的路径中最少的边数.那么每条路径就可以更新答案 \(ans=\min\{ans,edges+tmp[k-len]\}\).将当前子树的点存入 \(s2\) 中,处理完后再用 \(s2\) 内的路径更新 \(tmp\).
  • \(tmp\) 每次要初始化为 \(inf\) ,为了避免每次遍历所有点,可以记录哪些位置被修改过(记录在 \(s1\) 中),只用给它们赋值就可以了.
#include<bits/stdc++.h>
#define mp make_pair
#define inf 1e9
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
inline int read()
{
int out=0,fh=1;
char jp=getchar();
while ((jp>'9'||jp<'0')&&jp!='-')
jp=getchar();
if (jp=='-')
fh=-1,jp=getchar();
while (jp>='0'&&jp<='9')
out=out*10+jp-'0',jp=getchar();
return out*fh;
}
const int MAXN=2e5+10;
int ans=inf;
int cnt=0,head[MAXN],to[MAXN<<1],nx[MAXN<<1],val[MAXN<<1];
inline void addedge(int u,int v,int w)
{
++cnt;
to[cnt]=v;
nx[cnt]=head[u];
val[cnt]=w;
head[u]=cnt;
}
int n,k;
int vis[MAXN];
int totsiz,sonsiz[MAXN],siz[MAXN],mi,rt;
void findrt(int u,int fa)
{
siz[u]=1;
sonsiz[u]=0;
for(int i=head[u];i;i=nx[i])
{
int v=to[i];
if(v==fa || vis[v])
continue;
findrt(v,u);
siz[u]+=siz[v];
sonsiz[u]=max(sonsiz[u],siz[v]);
}
sonsiz[u]=max(sonsiz[u],totsiz-siz[u]);
if(sonsiz[u]<mi)
mi=sonsiz[u],rt=u;
}
int len[MAXN],edges[MAXN];
int tmp[1000000+10];
int s1[MAXN],s2[MAXN];
int tp1,tp2;
void getdis(int u,int fa)
{
if(k>=len[u])
ans=min(ans,edges[u]+tmp[k-len[u]]);
s2[++tp2]=u;
for(int i=head[u];i;i=nx[i])
{
int v=to[i];
if(v==fa || vis[v])
continue;
len[v]=len[u]+val[i];
// assert(len[v]<=1000000);
edges[v]=edges[u]+1;
getdis(v,u);
}
}
void solve(int u)
{
len[u]=edges[u]=0;
for(int i=1;i<=tp1;++i)
tmp[s1[i]]=inf;
s1[tp1=1]=u;
tmp[0]=0;
for(int i=head[u];i;i=nx[i])
{
int v=to[i];
if(vis[v])
continue;
tp2=0;
len[v]=val[i],edges[v]=1;
getdis(v,u);
for(int j=1;j<=tp2;++j)
{
v=s2[j];
tmp[len[v]]=min(tmp[len[v]],edges[v]);
s1[++tp1]=len[v];
}
}
}
void divide(int u)
{
solve(u);
vis[u]=1;
for(int i=head[u];i;i=nx[i])
{
int v=to[i];
if(vis[v])
continue;
mi=inf,totsiz=siz[v];
findrt(v,0);
divide(rt);
}
}
int main()
{
// freopen("testdata.in","r",stdin);
n=read(),k=read();
for(int i=1;i<n;++i)
{
int u=read()+1,v=read()+1,w=read();
addedge(u,v,w);
addedge(v,u,w);
}
for(int i=0;i<=1000000;++i)
tmp[i]=inf;
mi=inf,totsiz=n;
findrt(1,0);
divide(rt);
cout<<(ans==inf?-1:ans)<<endl;
return 0;
}

Luogu 4149 Race的更多相关文章

  1. [LUOGU] 4149 [IOI2011]Race

    点分治裸题 #include<iostream> #include<cstring> #include<cstdio> using namespace std; i ...

  2. 洛谷 4149 [IOI2011]Race——点分治

    题目:https://www.luogu.org/problemnew/show/P4149 第一道点分治! 点分治大约是每次找重心,以重心为根做一遍树形dp:然后对于该根的每个孩子,递归下去.递归之 ...

  3. 【Luogu P4149】[IOI2011]Race(点分治)

    自闭了几天后的我终于开始做题了..然后调了3h一道点分治板子题,调了一天一道IOI... 最后还是自己手造数据debug出来的... 这题一看:树上路径问题,已知路径长度求balabala,显然是点分 ...

  4. 【洛谷4149】[IOI2011] Race(点分治)

    点此看题面 大致题意: 给你一棵树,问长度为\(K\)的路径至少由几条边构成. 点分治 这题应该比较显然是点分治. 主要思路 与常见的点分治套路一样,由于\(K≤1000000\),因此我们可以考虑开 ...

  5. LUOGU P4149 [IOI2011]Race

    题目描述 给一棵树,每条边有权.求一条简单路径,权值和等于 KKK ,且边的数量最小. 输入输出格式 输入格式: 第一行:两个整数 n,kn,kn,k . 第二至 nnn 行:每行三个整数,表示一条无 ...

  6. Luogu 魔法学院杯-第二弹(萌新的第一法blog)

    虽然有点久远  还是放一下吧. 传送门:https://www.luogu.org/contest/show?tid=754 第一题  沉迷游戏,伤感情 #include <queue> ...

  7. Promise.race

    [Promise.race] 返回最先完成的promise var p1 = new Promise(function(resolve, reject) { setTimeout(resolve, 5 ...

  8. luogu p1268 树的重量——构造,真正考验编程能力

    题目链接:http://www.luogu.org/problem/show?pid=1268#sub -------- 这道题费了我不少心思= =其实思路和标称毫无差别,但是由于不习惯ACM风格的题 ...

  9. golang中的race检测

    golang中的race检测 由于golang中的go是非常方便的,加上函数又非常容易隐藏go. 所以很多时候,当我们写出一个程序的时候,我们并不知道这个程序在并发情况下会不会出现什么问题. 所以在本 ...

随机推荐

  1. git 提交某个内容

    git add 你所添加的文件或者文件夹 git commit git push

  2. HTML中table的td宽度无法固定问题

    设置了 width="10%" 依然会被内容撑大, 加了 style="word-break:break-all;" 属性就好了.效果是内容自动回车. 此属性不 ...

  3. 秒懂算法1——冒泡排序,及一种小改进(C#实现)

    算法思路: 重复走访每两个相邻元素,比较大小交换位置,直至排序完成. 有兴趣电话可以看一下这个[冒泡排序踢踏舞]的视频,很形象的演示了排序过程,额呵呵~~ 性质: 冒泡排序是一种原地排序(只有常数个元 ...

  4. linux环境变量 export命令详解

    由host $ export DVSDK="${HOME}/ti-dvsdk_dm368-evm_xx_xx_xx_xx"引发的问题 1.${HOME}:首先, HOME 是个变量 ...

  5. Session存储

    session其实分为服务器端Session和客户端Session. 当用户首次与Web服务器建立连接的时候,服务器会给用户分发一个sessionid作为标识.用户每次提交页面,浏览器都会把这个ses ...

  6. [sqlite] 数据库遇到的问题 “该字符串未被识别为有效的 DateTime”

    异常详细信息: System.FormatException: 该字符串未被识别为有效的 DateTime. 解决方案: 在日期保存到Sqlite数据库时转换一个类型,比如:string _now = ...

  7. redis安装配置记录

    环境:CentOS7,最小化安装 安装gcc wget # yum upgrade # yum install gcc # yum install wget 下载并安装redis # wget htt ...

  8. cookie和session的区别与联系

    http://www.cnblogs.com/s1nker/p/4876284.html 基本概念 对于许多人来说,都知道的是,cookie是存储在客户端的,可以用来放需要长期使用的内容,例如用户密码 ...

  9. SQL Server 2008 R2 使用 PIVOT 错误

    SQL Server 2008 R2 使用 PIVOT 错误! 'PIVOT' 附近有语法错误.您可能需要将当前数据库的兼容级别设置为更高的值,以启用此功能. 有关 ALTER DATABASE 的 ...

  10. node中的一些诡异bug

    这种bug一般是监听的端口号被占用了导致的,换个端口号!!!!