• 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 }
    “这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
  • 相关阅读:
    关于通用对象和通用函数的设计思想
    用ROOT 身份打开 文件管理器的 命令
    hibernate深入学习笔记
    hibernate简括
    hibernate先删除数据,紧接着执行插入时的异常解决之道——中间不能调用flush()、clear()等方法
    Maximum Gap (ARRAY SORT)
    Evaluate Reverse Polish Notation (STRINGTYPE CONVERTION)
    Max Points on a Line (HASH TABLE
    PHPnow实现多端口服务配置
    mcrypt 在 Linux 安装
  • 原文地址:https://www.cnblogs.com/Blogggggg/p/7348603.html
Copyright © 2020-2023  润新知