zoukankan      html  css  js  c++  java
  • bzoj2282[Sdoi2011]消防

    bzoj2282[Sdoi2011]消防

    题意:

    在树上找一条路径,使得端点到这条路径的距离最大值最小。

    题解:

    一个坑,就是这个路径可以不包含任意一条边,只包含一个节点。因此可以证明这条路径在树的直径上,把树的直径上的所有边存入一个序列,对直径上每个点求其它不在路径上的点与它的最大距离mxd,然后用双指针维护序列的一段使得和≤s,比较答案和序列两端到直径首末端的距离及序列中的点的最大mxd的较大值。序列中的点的最大mxd值用单调队列即可维护,怎么求树的直径呢?先对任意节点dfs/bfs求出最大距离的点,再对这个点作dfs/bfs求出与其距离最大的点,第二次遍历到第二个点所经过的路径就是树的直径。

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #define inc(i,j,k) for(int i=j;i<=k;i++)
     5 #define maxn 300010
     6 using namespace std;
     7 
     8 inline int read(){
     9     char ch=getchar(); int f=1,x=0;
    10     while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    11     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    12     return f*x;
    13 }
    14 int n,s,d[maxn],f[maxn],p[maxn],ed[maxn],mxd[maxn],tot,fr,ta,q1[maxn],q2[maxn],l,r,now,ans,sm[maxn];
    15 bool vis[maxn];
    16 struct e{int t,w,n;}; e es[maxn*3]; int g[maxn],ess;
    17 void pe(int f,int t,int w){
    18     es[++ess]=(e){t,w,g[f]}; g[f]=ess; es[++ess]=(e){f,w,g[t]}; g[t]=ess;
    19 }
    20 void dfs1(int x,int fa){
    21     for(int i=g[x];i;i=es[i].n)if(es[i].t!=fa)d[es[i].t]=d[x]+es[i].w,dfs1(es[i].t,x);
    22 }
    23 void dfs2(int x){
    24     for(int i=g[x];i;i=es[i].n)if(i!=f[x])d[es[i].t]=d[x]+es[i].w,f[es[i].t]=i^1,dfs2(es[i].t);
    25 }
    26 void dfs3(int x){
    27     for(int i=g[x];i;i=es[i].n)if(!vis[es[i].t])
    28         d[es[i].t]=d[x]+es[i].w,mxd[0]=max(mxd[0],d[es[i].t]),vis[es[i].t]=1,dfs3(es[i].t);
    29 }
    30 int main(){
    31     n=read(); s=read(); ess=1; inc(i,1,n-1){int a=read(),b=read(),c=read(); pe(a,b,c);}
    32     d[1]=0; dfs1(1,0); int mx1=1; inc(i,1,n)if(d[i]>d[mx1])mx1=i; d[mx1]=0; f[mx1]=0; dfs2(mx1);
    33     int mx2=mx1; inc(i,1,n)if(d[i]>d[mx2])mx2=i;
    34     for(int i=mx2;i;i=es[f[i]].t)tot++,p[tot]=i,ed[tot]=es[f[i]].w,vis[i]=1;
    35     inc(i,1,tot)d[p[i]]=0,mxd[0]=0,dfs3(p[i]),mxd[i]=mxd[0],sm[i]=sm[i-1]+ed[i];
    36     l=1; r=1; now=ed[1]; fr=ta=1; q1[1]=mxd[1]; q2[1]=1; ans=0x3fffffff;
    37     while(l<=r&&l<=tot-1){
    38         while(r<=tot-1&&now<=s){
    39             ans=min(ans,max(max(q1[fr],sm[l-1]),sm[tot-1]-sm[r-1])); r++;
    40             while(fr<=ta&&mxd[r]>q1[ta])ta--; q1[++ta]=mxd[r]; q2[ta]=r; now+=ed[r];
    41         }
    42         if(q2[fr]==l)fr++; now-=ed[l]; l++;
    43         if(l<=tot-1&&now<=s)ans=min(ans,max(max(q1[fr],sm[l-1]),sm[tot-1]-sm[r]));
    44     }
    45     inc(i,1,tot)ans=min(ans,max(max(mxd[i],sm[i-1]),sm[tot-1]-sm[i-1]));
    46     printf("%d",ans); return 0;
    47 }

    20160715

  • 相关阅读:
    【Android】12.0 UI开发(三)——列表控件ListView的简单实现2
    【Android】11.0 UI开发(二)——列表控件ListView的简单实现1
    【Android】10.0 UI开发——如何编写程序界面、常见控件的使用
    【转载】从创业者角度看《印度合伙人 Padman》后的一点感受
    【代码笔记】Java常识性基础补充(二)——数组、ArrayList集合、ASCII编码、 eclipse基础操作、eclipse调试、eclipse项目导入、eclipse快捷键
    Android 实现高斯模糊效果和圆角图片
    Android 获取当前系统时间
    Android RecycleView悬浮按钮点击返回顶部
    eclipse连接mysql
    mysql的增删改查语句
  • 原文地址:https://www.cnblogs.com/YuanZiming/p/5674929.html
Copyright © 2011-2022 走看看