zoukankan      html  css  js  c++  java
  • [IOI2013] dreaming 梦想 题解

    由于题目要使最长路径最短,于是很容易想到贪心策略:


    每棵树和其它树连边的点一定是这棵树上能走到的最远距离最短的的点(由于本人语文水平太菜,这句话有点绕 qwq)

    如果我们把上述的最短距离称作半径 $r$,$1,2,3...$ 是树按照 $r$ 排序后的。那么最后链接成的树应该长这样:

    那么最后的答案只有三种情况:

    1、原树的最长直径

    2、$r_1+r_2+l$

    3、$r_2+r_3+l*2$

    求个 $max$ 就好了~~~

    至于树的半径和直径怎么求。注意到树上离某个点最远的点一定是树的直径的某个端点,于是就可以 $O(n)$ dfs求出。

    /*

    注意每次dfs前清空数组不能用memset,不然效率会被卡到 $O(n^2)$

    我就因为这个T了好久,以为是常数问题,于是代码中加了很多无用的卡常操作,导致它跑的特别快。。。

    */

    代码

      1 #include<cstdio>
      2 #include<algorithm>
      3 #define Int register int
      4 #define N 100005
      5 
      6 inline void rd(int &x){
      7     x=0;char c=getchar();
      8     while(c<'0'||c>'9')c=getchar();
      9     while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^'0'),c=getchar();
     10 }
     11 
     12 int n,m,l;
     13 
     14 int hd[N],_hd;
     15 struct edge{
     16     int v,w,nxt;
     17 }e[N<<1];
     18 inline void addedge(int u,int v,int w){
     19     e[++_hd]=(edge){v,w,hd[u]};
     20     hd[u]=_hd;
     21 }
     22 
     23 bool flg;//为了卡常 
     24 int q[N],_q;
     25 
     26 int dis[2][N];
     27 bool vis[N];
     28 inline void dfs(Int u,Int fa,Int opt){
     29     if(!flg)
     30         q[++_q]=u;
     31     vis[u]=1;
     32     for(Int i=hd[u];i;i=e[i].nxt){
     33         Int v=e[i].v,w=e[i].w;
     34         if(v==fa)
     35             continue;
     36         dis[opt][v]=dis[opt][u]+w;
     37         dfs(v,u,opt);
     38     }
     39 }
     40 
     41 inline int fnd(Int u){
     42     for(Int i=1;i<=_q;i++){
     43         Int v=q[i];
     44         dis[0][q[i]]=0;
     45     }//这里千万不能用memset 
     46     dfs(u,0,0);
     47     flg=1;
     48     Int res=u;
     49     for(Int i=1;i<=_q;i++){
     50         Int v=q[i];
     51         if(dis[0][v]>dis[0][res])
     52             res=v;
     53     }
     54     return res;
     55 }
     56 
     57 int r1,r2,r3,ans,cnt;//r1、r2、r3为前三大的半径,ans一开始为最长直径(第一种情况),cnt表示原来有几棵树 
     58 inline void sol(Int u){
     59     cnt++;
     60     flg=_q=0;
     61     dfs(fnd(fnd(u)),0,1);//最里面的fnd返回的是直径的一个端点,第二个fnd更新dis[0],返回另一个端点,dfs更新dis[1] 
     62     Int r=1e9;
     63     for(Int i=1;i<=_q;i++){
     64         Int v=q[i],disv=std::max(dis[0][v],dis[1][v]);
     65         r=std::min(r,disv);//更新当前树的半径 
     66         ans=std::max(ans,disv);//更新最大直径 
     67     }
     68     if(r>r1){
     69         r3=r2;
     70         r2=r1;
     71         r1=r;
     72     }
     73     else if(r>r2){
     74         r3=r2;
     75         r2=r;
     76     }
     77     else if(r>r3)
     78         r3=r;
     79 }
     80 
     81 int main(){
     82     rd(n),rd(m),rd(l);
     83     for(Int i=1;i<=m;i++){
     84         Int u,v,w;
     85         rd(u),rd(v),rd(w);
     86         addedge(++u,++v,w);
     87         addedge(v,u,w);
     88     }
     89     for(Int i=1;i<=n;i++)
     90         if(!vis[i])
     91             sol(i);
     92     if(cnt>1)
     93         ans=std::max(ans,r1+r2+l);//第二种情况 
     94     if(cnt>2)
     95         ans=std::max(ans,r2+r3+(l<<1));//第三种情况 
     96     printf("%d
    ",ans);
     97 
     98     #define w 0
     99     return ~~('0')?(0^w^0):(0*w*0);
    100 } 
  • 相关阅读:
    Huawei vlan 配置及vlan 间通讯
    Huawei DHCP 中继配置实例
    Huawei DHCP 全局配置与接口配置
    Cisco DHCP 配置方法
    VS Code的golang开发配置 之 代码提示
    天气服务API文档 第1版
    Android 让图片等比例缩放的三种方法
    Jar mismatch! Fix your dependencies
    android ActionBarSherlock使用说明
    Only the original thread that created a view hierarchy can touch its views.
  • 原文地址:https://www.cnblogs.com/Y25t/p/12237174.html
Copyright © 2011-2022 走看看