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

    题目大意:
      给你一棵n个结点的带边权的树,问长度恰好为k的路径至少经过多少条边?

    思路:
      重心剖分。
      对于每次剖分出来的子树,存一下从根出发的长度为i的路径至少经过几条边f[i]。
      注意要保证经过根结点,所以一次整棵树DFS结束后才能更新f。
      重置数组f的时候,不能从i到k重置,而应该重新遍历整棵树,把会用到的那些值重置。
      最后就是各种低级错误,比如一开始把size[x]+=size[y]中x和y打反,导致除了叶子结点的子树,其它子树大小都是0,剖不到重心上。
      最后还是拼命TLE,最后发现原来是freopen没删掉。

      1 #pragma GCC optimize(3)
      2 #pragma GCC optimize("unroll-loops")
      3 #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
      4 #include<cstdio>
      5 inline int getint() {
      6     register char ch;
      7     while(!__builtin_isdigit(ch=getchar()));
      8     register int x=ch^'0';
      9     while(__builtin_isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     10     return x;
     11 }
     12 const int inf=0x7fffffff;
     13 const int N=200001,K=1000001;
     14 int h[N],to[N<<1],w[N<<1],next[N<<1],cnt;
     15 inline void add_edge(const int &u,const int &v,const int &l) {
     16     to[++cnt]=v; w[cnt]=l; next[cnt]=h[u]; h[u]=cnt;
     17     to[++cnt]=u; w[cnt]=l; next[cnt]=h[v]; h[v]=cnt;
     18 }
     19 int size[N],f[K],s,mn,cur,k,ans;
     20 bool mark[N];
     21 inline int max(const int &a,const int &b) {
     22     return a>b?a:b;
     23 }
     24 inline int min(const int &a,const int &b) {
     25     return a<b?a:b;
     26 }
     27 void dfs(const int &x,const int &par) {
     28     size[x]=1;
     29     int mx=0;
     30     for(int i=h[x];i;i=next[i]) {
     31         const int &y=to[i];
     32         if(y==par||mark[y]) continue;
     33         dfs(y,x);
     34         size[x]+=size[y];
     35         mx=max(mx,size[y]);
     36     }
     37     mx=max(mx,s-size[x]);
     38     if(mx<mn) {
     39         mn=mx;
     40         cur=x;
     41     }
     42 }
     43 inline int get_center(const int &x) {
     44     mn=inf;
     45     dfs(x,0);
     46     return cur;
     47 }
     48 int get_size(const int &x,const int &par) {
     49     int size=1;
     50     for(int i=h[x];i;i=next[i]) {
     51         const int &y=to[i];
     52         if(y==par||mark[y]) continue;
     53         size+=get_size(y,x);
     54     }
     55     return size;
     56 }
     57 void dp(const int &x,const int &par,const int &dis,const int &dep) {
     58     if(dis>k) return;
     59     if(dis==k||f[k-dis]!=inf) {
     60         ans=min(ans,dep+f[k-dis]);
     61     }
     62     for(int i=h[x];i;i=next[i]) {
     63         const int &y=to[i];
     64         if(y==par||mark[y]) continue;
     65         dp(y,x,dis+w[i],dep+1);
     66     }
     67 }
     68 void set(const int &x,const int &par,const int &dis,const int &dep) {
     69     if(dis>k) return;
     70     f[dis]=min(f[dis],dep);
     71     for(int i=h[x];i;i=next[i]) {
     72         const int &y=to[i];
     73         if(y==par||mark[y]) continue;
     74         set(y,x,dis+w[i],dep+1);
     75     }
     76 }
     77 void reset(const int &x,const int &par,const int &dis) {
     78     if(dis>k) return;
     79     f[k-dis]=inf;
     80     for(int i=h[x];i;i=next[i]) {
     81         const int &y=to[i];
     82         if(y==par||mark[y]) continue;
     83         reset(y,x,dis+w[i]);
     84     }
     85 }
     86 void solve(const int &x) {
     87     s=get_size(x,0);
     88     const int u=get_center(x);
     89     mark[u]=true;
     90     for(int i=h[u];i;i=next[i]) {
     91         const int &v=to[i];
     92         if(mark[v]) continue;
     93         solve(v);
     94     }
     95     reset(u,0,0);
     96     f[0]=0;
     97     for(register int i=h[u];i;i=next[i]) {
     98         const int &v=to[i];
     99         if(mark[v]) continue;
    100         dp(v,u,w[i],1);
    101         set(v,u,w[i],1);
    102     }
    103     mark[u]=false;
    104 }
    105 int main() {
    106     const int n=getint();
    107     k=getint();
    108     for(register int i=1;i<n;i++) {
    109         const int u=getint()+1,v=getint()+1,w=getint();
    110         add_edge(u,v,w);
    111     }
    112     ans=inf;
    113     solve(1);
    114     __builtin_printf("%d
    ",ans!=inf?ans:-1);
    115     return 0;
    116 }
  • 相关阅读:
    node nmp 的关键信息
    PHP中定义常量的区别,define() 与 const
    mac电脑如何快速显示桌面及切换应用
    Mac拷贝/复制文件夹路径快捷键
    比 file_get_contents() 更优的 cURL 详解(附实例)
    PHP fopen/file_get_contents与curl性能比较
    在phpstorm中如何对比文件呢?
    PHP 基础篇
    MySQL 中视图和表的区别以及联系是什么?
    MAC将根目录文件夹的权限赋给用户
  • 原文地址:https://www.cnblogs.com/skylee03/p/8194305.html
Copyright © 2011-2022 走看看