zoukankan      html  css  js  c++  java
  • IOI2011 Race [点分治]

    题意

      给一棵树,每条边有权。求一条简单路径,权值和等于 $K$,且边的数量最小。


      点分治,求距离时带上经过边的数量即可。用的第一种写法(下面)。


    食用淀粉质注意事项

    1、 统计子树内答案的两种写法: 跟树形dp一样将某子树与前面的子树合并   或者是   考虑所有子树的答案再容斥,减去不合法的一棵子树内答案。

    2、好好写求重心,千万不要写假!!!假淀粉害死人

      注意每次遍历先初始化$f[x]=0$,要有子树大小$S$。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 const int N=200010;
     6 const int M=1000010;
     7 const int inf=0x3f3f3f3f;
     8 int n,k,x,y,z,rt,f[N],size[N],ans=inf,S;
     9 int dis[N],d[N],his[N],h[N],rec[M],t[N];
    10 bool vis[N];
    11 int head[N],to[N<<1],nxt[N<<1],w[N<<1],p;
    12 inline int read() {
    13     int re=0; char ch=getchar();
    14     while (ch<'0'||ch>'9') ch=getchar();
    15     while (ch>='0'&&ch<='9') re=re*10+ch-48,ch=getchar();
    16     return re;
    17 }
    18 inline void add(int x,int y,int z) {
    19     to[++p]=y; nxt[p]=head[x]; w[p]=z; head[x]=p;
    20     to[++p]=x; nxt[p]=head[y]; w[p]=z; head[y]=p;
    21 }
    22 void get_rt(int x,int fa) {
    23     size[x]=1; f[x]=0;//here
    24     for (int i=head[x]; i; i=nxt[i]) {
    25         if (to[i]==fa || vis[to[i]]) continue;
    26         get_rt(to[i],x);
    27         size[x]+=size[to[i]];
    28         if (size[to[i]]>f[x]) f[x]=size[to[i]];
    29     }
    30     f[x]=max(f[x],S-size[x]);//here
    31     if (f[x]<f[rt]) rt=x;
    32 }
    33 void get_dis(int x,int fa) {
    34     if (d[x]<=k) dis[++dis[0]]=d[x],his[dis[0]]=h[x];
    35     for (int i=head[x]; i; i=nxt[i]) {
    36         if (to[i]==fa || vis[to[i]]) continue;
    37         d[to[i]]=d[x]+w[i]; h[to[i]]=h[x]+1;
    38         if (d[to[i]]<=k) get_dis(to[i],x);
    39     }
    40 }
    41 void dfs(int x) {
    42     vis[x]=1; int T=0;
    43     for (int i=head[x]; i; i=nxt[i]) {
    44         if (vis[to[i]]) continue;
    45         dis[0]=0; d[to[i]]=w[i],h[to[i]]=1; get_dis(to[i],x);
    46         for (int i=1; i<=dis[0]; i++) 
    47             if (~rec[k-dis[i]]) ans=min(ans,his[i]+rec[k-dis[i]]); 
    48         for (int i=1; i<=dis[0]; i++) 
    49             t[++T]=dis[i],rec[dis[i]]=~rec[dis[i]] ? min(rec[dis[i]],his[i]):his[i];
    50     }
    51     while (T) rec[t[T--]]=-1;
    52     for (int i=head[x]; i; i=nxt[i]) {
    53         if (vis[to[i]]) continue;
    54         S=size[to[i]]; f[rt=0]=inf;
    55         get_rt(to[i],x); dfs(rt);
    56     }
    57 }
    58 int main() {
    59     n=read(); k=read();
    60     for (int i=1; i<n; i++) x=read()+1,y=read()+1,z=read(),add(x,y,z);
    61     memset(rec,-1,sizeof rec); rec[0]=0;
    62     S=n; f[rt=0]=inf;
    63     get_rt(1,0); dfs(rt);
    64     printf("%d\n",ans==inf ? -1:ans);
    65     return 0;
    66 }
  • 相关阅读:
    Oracle忘记用户名和密码以及管理员用户新增修改删除用户
    Oracle11.2安装和完全卸载及卸载后重装等问题
    软件测试之路2
    软件测试之路1
    Git入门笔记
    CentOS 6.5下二进制安装 MySQL 5.6
    十款压力测试工具
    tomcat 内存设置
    tomcat 安全
    tomcat 模式详解
  • 原文地址:https://www.cnblogs.com/hnooo/p/10125494.html
Copyright © 2011-2022 走看看