zoukankan      html  css  js  c++  java
  • BZOJ1509 [NOI2003]逃学的小孩 树型DP

    题目:

    分析:

      首先明确我们是要求 min(dist[C][A],dist[C][B])+dist[A][B].

      我们把C当成树根,第一我们可以发现min里面取dist[C][A]或者dist[C][B]其实是一个意思(因为可以交换)。

      接着可以发现dist[A][B]实际上是这棵树的直径。如果不是,那么答案一定不是最优的。我们可以这样去想:

        如果dist[A][B]不是直径,那么一定有dist[C][A']使得比dist[C][A]更优,而且A'一定是直径的一个端点:-)。加号的前面和后面都不是最优的,那么答案也不是最优的。

      所以我们可以先处理出树的直径,接着枚举点C使得它到两个端点的距离的最小值最大。

      时间复杂度O(n),空间复杂度O(n)。  

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<vector>
     6 using namespace std;
     7  
     8 typedef long long ll;
     9  
    10 struct edge{
    11     ll to,w;
    12 };
    13  
    14 const ll maxn = 200010;
    15  
    16 ll n,m;
    17 vector <edge> g[maxn];
    18 ll arr[maxn],dep[maxn];
    19  
    20 void dfs(int now,ll data){
    21     arr[now] = 1;
    22     dep[now] = min(dep[now],data);
    23     for(int i=0;i<g[now].size();i++){
    24     if(arr[g[now][i].to]) continue;
    25     dfs(g[now][i].to,g[now][i].w+data);
    26     }
    27     arr[now] = 0;
    28 }
    29  
    30 int get_max(){
    31     dep[0] = 0;
    32     int maxx = 0;
    33     for(int i=1;i<=n;i++){
    34     if(dep[maxx] < dep[i]) maxx = i;
    35     }
    36     return maxx;
    37 }
    38  
    39 void read(){
    40     scanf("%lld%lld",&n,&m);
    41     for(ll i=1;i<=m;i++){
    42     ll x,y,c; scanf("%lld%lld%lld",&x,&y,&c);
    43     g[x].push_back((edge){y,c});
    44     g[y].push_back((edge){x,c});
    45     }
    46 }
    47  
    48 void work(){
    49     memset(dep,127/3,sizeof(dep));
    50     dfs(1,0);//get the farthest point in tree
    51     ll ans=0,t1 = get_max();
    52     memset(dep,127/3,sizeof(dep));
    53     dfs(t1,0);//another point
    54     ll t2 = get_max();
    55     ans += dep[t2];//zhijing
    56     dfs(t2,0);
    57     ll maxx = 0;
    58     for(int i=1;i<=n;i++)
    59     maxx = max(maxx,dep[i]);
    60     ans += maxx; // farthest dian for zhijing
    61     printf("%lld",ans);
    62 }
    63  
    64 int main(){
    65     read();
    66     work();
    67     return 0;
    68 }
  • 相关阅读:
    你敢说自己了解单例模式?
    关于线程池,那些你还不知道的事
    Dubbo透传traceId/logid的一种思路
    当BeanUtils遇到泛型
    Oval框架如何校验枚举类型的一种思路
    HttpClient(4.5.x)正确的使用姿势
    HttpClient官方sample代码的深入分析(连接池)
    Jaxb如何优雅的处理CData
    JAXB性能优化
    Jaxb对xml报文头的小修小改
  • 原文地址:https://www.cnblogs.com/1-1-1-1/p/6911260.html
Copyright © 2011-2022 走看看