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 } 
  • 相关阅读:
    (4.25)Sqlserver中 登录用户只能看到自己拥有权限的库
    【查阅】mysql配置文件/参数文件重要参数笔录(my.cnf)
    【监控笔记】【2.5】DML(CDC)、DDL(DDL触发器)跟踪数据更改,数据库审计
    SQL Server 2008中的CDC(Change Data Capture)功能使用及释疑
    【监控笔记】【2.4】SQL Server中的 Ring Buffer 诊断各种系统资源压力情况
    【监控笔记】【2.3】扩展事件——慢查询SQL(执行超过3S的SQL)
    【监控笔记】【2.2】扩展事件——死锁监控
    最小配置启动SQL SERVER,更改SQL Server最大内存大小导致不能启动的解决方法
    【监控笔记】【2.1】扩展事件
    【扩展事件】跟踪超过3秒的SQL
  • 原文地址:https://www.cnblogs.com/Y25t/p/12237174.html
Copyright © 2011-2022 走看看