• 洛谷 P1099 树网的核(树的直径+贪心)


    题目链接:https://www.luogu.com.cn/problem/P1099

    用两边DFS求出直径,用f记录fa,这样就记录下了直径的路径,将直径上的点vis标记为1。然后枚举左右端点(或者尺取法,但不会)。

    贪心考虑对答案的贡献:

    假设直径的两个端点为a和b,当前左右端点为i,j,

    对答案的贡献只有a,i之间的距离、b,j之间的距离、i,j中每个节点的子树的最远距离。

    那么可以对于直径上的每一个节点做一次关于它的子树(除直径)的DFS,找出子树最远距离,存在dt[]中。注意不要每更换一次左右端点就重新求一遍,因为vis
    会影响(坑)。

    AC代码:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<queue>
     5 using namespace std;
     6 int n,s;
     7 const int N=400;
     8 int tot,ans=0x7f7f7f7f,anss,ansss;
     9 int head[N];
    10 int f[N],maxd,dis[N],diss[N],dt[N];
    11 int p,vis[N];
    12 struct node{
    13     int to,next,w;
    14 }edge[N<<1];
    15 void add(int u,int v,int w){
    16     edge[tot].to=v;
    17     edge[tot].next=head[u];
    18     edge[tot].w=w;
    19     head[u]=tot++;
    20 }
    21 void DFS(int u,int fa){
    22     f[u]=fa;
    23     if(maxd<dis[u]){
    24         maxd=dis[u];
    25         p=u;
    26     }
    27     for(int i=head[u];i!=-1;i=edge[i].next){
    28         int v=edge[i].to;
    29         if(vis[v]||v==fa) continue;
    30         vis[v]=1;
    31         dis[v]=dis[u]+edge[i].w;
    32         DFS(v,u);
    33     }
    34 }
    35 void DFSD(int u){
    36     if(diss[u]>maxd) maxd=diss[u];
    37     for(int i=head[u];i!=-1;i=edge[i].next){
    38         int v=edge[i].to;
    39         if(vis[v]) continue;
    40         vis[v]=1;
    41         diss[v]=diss[u]+edge[i].w;
    42         DFSD(v);
    43     }
    44 }
    45 int main(){
    46     memset(head,-1,sizeof(head));
    47     memset(f,-1,sizeof(f));
    48     scanf("%d%d",&n,&s);
    49     for(int i=1;i<n;i++){
    50         int u,v,w;
    51         scanf("%d%d%d",&u,&v,&w);
    52         add(u,v,w); add(v,u,w); 
    53     }
    54     DFS(1,-1);
    55     memset(dis,0,sizeof(dis));
    56     memset(f,-1,sizeof(f));
    57     memset(vis,0,sizeof(vis));
    58     int a=p;
    59     maxd=0;
    60     DFS(p,-1);
    61     int b=p;
    62     memset(vis,0,sizeof(vis));
    63     for(int i=b;i!=-1;i=f[i]) vis[i]=1;
    64     for(int i=b;i!=-1;i=f[i]){
    65         for(int j=i;j!=-1&&dis[i]-dis[j]<=s;j=f[j]){
    66             anss=max(dis[b]-dis[i],dis[j]);
    67             for(int k=i;k!=f[j];k=f[k]){
    68                 maxd=0;
    69                 if(dt[k]) maxd=dt[k];
    70                 else { DFSD(k); dt[k]=maxd;}
    71                 anss=max(anss,maxd);
    72             }
    73             ans=min(ans,anss);
    74         }
    75     }
    76     printf("%d",ans);
    77     return 0;
    78 }
    AC代码
  • 相关阅读:
    mongoDB使用
    mac环境下mongodb的安装和使用
    statrc部分
    权限部分
    在Linux 安装Python3.5.6详细文档!!!!
    linux回顾
    linux服务配置
    路飞ORM练习
    考试题-路飞中期(卷一)
    git hub命令,上传到github
  • 原文地址:https://www.cnblogs.com/New-ljx/p/13698081.html
Copyright © 2020-2023  润新知