• bzoj2599/luogu4149 [IOI2011]Race (点分治)


    点分治。WA了一万年。

    重点就是统计答案的方法

    做法一(洛谷AC bzojWA 自测WA):

    做点x时记到x距离为k的边数最小值为dis[k],然后对每一对有值的dis[i]和dis[K-i],给ans[A[i]+A[K-i]]++,然后因为统计到了一部分不合法答案,就做x的儿子,给ans变成--,最后查ans的第一个有值的点,就是答案。

    错误原因:可能这个点有一个的不合法答案,但它的边数在等距离中不是最小的,他就不会被统计,等到一会减掉错误答案的时候却会被减掉,然后就错了

    做法二 (洛谷TLE 洛谷+O2AC bzojTLE 自测AC):

    记下来到x所有点的距离和边数,按照距离排序,然后一边正着做,一边倒着做,找到所有距离和==K的对,统计到ans[边数和]里,也是要做儿子来减掉不合法答案

    错误原因:常数太大

    做法三  (AC)(感谢sbw大佬的热心指点orz):

    也是记一个dis[i]表示距离为i的最短边数,但我们在做x这个点的时候找x的每个儿子这个子树去做,每次先统计答案(ans=min{ans,dep+dis[K-i]}),再更新dis[i]数组,这样就相当于我们不会查到两端点都在同一子树的答案,就是所有找到的都是合法的

    (要把dis[0]先给成零,因为这条路径是有可能以根节点为端点的)

     1 #include<bits/stdc++.h>
     2 #define pa pair<int,int>
     3 #define ll long long
     4 using namespace std;
     5 const int maxn=200020,maxk=1000010;
     6 
     7 inline ll rd(){
     8     ll x=0;char c=getchar();int neg=1;
     9     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
    10     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    11     return x*neg;
    12 }
    13 
    14 int N,K;
    15 struct Edge{
    16     int b,ne,l;
    17 }eg[maxn*2];
    18 int egh[maxn],ect;
    19 int siz[maxn],pct;
    20 bool flag[maxn];
    21 int root,ms,smsiz;
    22 int dis[maxk],ans=0x3f3f3f3f;
    23 queue<int> dq;
    24 
    25 
    26 inline void adeg(int a,int b,int l){
    27     eg[++ect].b=b;eg[ect].l=l;eg[ect].ne=egh[a];egh[a]=ect;
    28 }
    29 
    30 void getroot(int x,int f){
    31     siz[x]=1;int mm=0;
    32     for(int i=egh[x];i;i=eg[i].ne){
    33         int b=eg[i].b;if(flag[b]||b==f) continue;
    34         getroot(b,x);
    35         siz[x]+=siz[b];mm=max(siz[b],mm);
    36     }mm=max(smsiz-siz[x],mm);
    37     if(mm<ms) ms=mm,root=x;
    38 }
    39 
    40 void getdis(int x,int f,int d,int dep){
    41     if(d<=K){
    42         if(dis[d]>2e5) dq.push(d);
    43         dis[d]=min(dis[d],dep);
    44     }else return;
    45     for(int i=egh[x];i;i=eg[i].ne){
    46         int b=eg[i].b;if(flag[b]||b==f) continue;
    47         getdis(b,x,d+eg[i].l,dep+1);
    48     }
    49 }
    50 void calans(int x,int f,int d,int dep){
    51     if(d<=K){
    52         if(dis[K-d]<=2e5) ans=min(ans,dep+dis[K-d]);
    53     }else return;
    54     for(int i=egh[x];i;i=eg[i].ne){
    55         int b=eg[i].b;if(flag[b]||b==f) continue;
    56         calans(b,x,d+eg[i].l,dep+1);
    57     }
    58 }
    59 
    60 inline void solve(int x){
    61     flag[x]=1;
    62     for(int i=egh[x];i;i=eg[i].ne){
    63         int b=eg[i].b;if(flag[b]) continue;
    64         calans(b,x,eg[i].l,1);
    65         getdis(b,x,eg[i].l,1);
    66     }while(!dq.empty()) dis[dq.front()]=0x3f3f3f3f,dq.pop();
    67     int ss=smsiz;
    68     for(int i=egh[x];i;i=eg[i].ne){
    69         int b=eg[i].b;if(flag[b]) continue;
    70         ms=0x3f3f3f3f;smsiz=siz[b]>siz[x]?ss-siz[x]:siz[b];
    71         getroot(b,x);solve(root);
    72     }
    73 }
    74 
    75 int main(){
    76     int i,j,k;
    77     N=rd(),K=rd(); 
    78     for(i=1;i<N;i++){
    79         int a=rd()+1,b=rd()+1,c=rd();
    80         adeg(a,b,c);adeg(b,a,c);
    81     }memset(dis,127,sizeof(dis));dis[0]=0;
    82     smsiz=N;ms=0x3f3f3f3f;getroot(1,0);
    83     solve(root);
    84     if(ans<=2e5) printf("%d
    ",ans);
    85     else printf("-1
    ");
    86     return 0;
    87 }
  • 相关阅读:
    编译错误error:&nbsp;invalid&amp;nbsp…
    移植OK6410&#039;S&nbsp;dm9000ae…
    JavaScript 正则表达式-严格匹配
    JavaScript indexOf() 方法
    JavaScript splice() 方法
    Css文字效果
    知识点-语句
    知识点—变量、运算符(表达式)
    WPF RichTextBox相关总结
    WPF调用图片路径,或资源图片
  • 原文地址:https://www.cnblogs.com/Ressed/p/9648815.html
Copyright © 2020-2023  润新知