zoukankan      html  css  js  c++  java
  • CF832D

    题目链接:http://codeforces.com/contest/832/problem/D

    题目大意:在一个无向图上,给出三个点,以其中一个点为终点,另外两个点为起点,请问如何安排起点和终点可以使得从两个起点走最短路到终点所共同经过的路径的长度最长?

    解题思路:任取一个点作为根建立一棵树(为什么可以建成一棵树?它不会有环吗?请看题目中的这一句:“The underground has n stations connected with n - 1 routes so that each route connects two stations, and it is possible to reach every station from any other.”),要求树中任意两点x,y的距离,其实只要先求出两点的公共祖先u,然后其距离便是 |depth[x]+depth[y]-2*depth[u]| 。对于一组确定的终点和起点,其共同路径长度就是 (dis(s1,t) + dis(s2,t) - dis(s1,s2))/2+1 (不理解的话稍微画一下图,至于为什么+1?根节点也要算哦亲)。具体请看代码(模板来自《挑战》)。

    AC代码:

      

     1 #include <cstdio>
     2 #include <vector>
     3 #include <cmath>
     4 using namespace std;
     5 const int maxn=1e5+5;
     6 vector<int> G[maxn];
     7 int log_max_v;
     8 int parent[25][maxn];
     9 int depth[maxn],s[5];
    10 int n,q;
    11 void dfs(int v,int p,int d){
    12     parent[0][v]=p;
    13     depth[v]=d;
    14     for(int i=0;i<G[v].size();i++){
    15         if(G[v][i]!=p)  dfs(G[v][i],v,d+1);
    16     }
    17 }
    18 void init(){
    19     dfs(1,-1,0);
    20     for(int k=0;k+1<20;k++){
    21         for(int v=1;v<=n;v++){
    22             if(parent[k][v]<0)  parent[k+1][v]=-1;
    23             else parent[k+1][v]=parent[k][parent[k][v]];
    24         }
    25     }
    26 }
    27 int lca(int u,int v){
    28     if(depth[u]>depth[v])   swap(u,v);
    29     for(int k=0;k<20;k++){
    30         if((depth[v]-depth[u])>>k&1){
    31             v=parent[k][v];
    32         }
    33     }
    34     if(u==v)    return u;
    35     for(int k=20;k>=0;k--){
    36         if(parent[k][u]!=parent[k][v]){
    37             u=parent[k][u];
    38             v=parent[k][v];
    39         }
    40     }
    41     return parent[0][u];
    42 }
    43 int dis(int a,int b){
    44     int u=lca(a,b);
    45     return abs(depth[a]+depth[b]-depth[u]*2);
    46 }
    47 int main()
    48 {
    49     scanf("%d%d",&n,&q);
    50     int p;
    51     for(int i=2;i<=n;i++){
    52         scanf("%d",&p);
    53         G[i].push_back(p);
    54         G[p].push_back(i);
    55     }
    56     init();
    57     while(q--){
    58         for(int i=0;i<3;i++)
    59             scanf("%d",&s[i]);
    60         
    61         int ans=0;
    62         for(int i=0;i<3;i++){
    63             int a=(i+1)%3,b=(i+2)%3;
    64             int temp=(dis(s[a],s[i])+dis(s[b],s[i])-dis(s[a],s[b]))/2;
    65             if(temp>ans)    ans=temp;
    66         }
    67         printf("%d
    ",ans+1);
    68     }
    69 
    70     return 0;
    71 }
    “这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
  • 相关阅读:
    div标签和span标签的简单区别
    方法重载的好处及区别
    异步计算工具
    设置"用于统计的冗余字段"要谨慎
    如何建立索引
    NFS,Memcached,Tokyo tyrant实现session共享性能测试
    mysql cache功能小记
    PHP程序员也要学会使用“异常”
    xdebug: var_dump函数设置
    用shell写个简单的log监控程序
  • 原文地址:https://www.cnblogs.com/Blogggggg/p/7348603.html
Copyright © 2011-2022 走看看