zoukankan      html  css  js  c++  java
  • 距离咨询

    【题目描述】

    农夫约翰有N(2 <= N <= 40000)个农场,标号为1~N,有M(2 <= M <= 40000)条的不同的垂直或水平的道路连接着农场,道路的长度不超过1000。这些农场的分布就像下面的地图一样,在图中农场用F1~F7表示:

    每个农场最多能在东西南北四个方向连接4个不同的农场,农场只会处在道路的两端,道路不会交叉而且每对农场之间有且仅有一条道路。约翰只知道每一条道路的信息如下:

    从农场23往南经距离10到达农场17;

    从农场1往东经距离7到达农场17;

    ······

    现有一张如上的地图以及K个问题,每个问题包括两个农场的编号,询问它们之间的距离。

    【输入描述】

    第一行输入两个整数N和M;

    接下来M行,每行输入四个整数F1、F2、L、D,分别表示两个农场的编号、道路的长度、F1到F2的方向N、E、S、W;

    接下来一行输入一个整数K(1 <= K <= 10000);

    接下来K行,每行输入两个整数,表示2个农场。

    【输出描述】

    对于每个问题,输出一个整数,表示答案。

    【样例输入】

    7 6

    1 6 13 E

    6 3 9 E

    3 5 7 S

    4 1 3 N

    2 4 20 W

    4 7 2 S

    3

    1 6

    1 4

    2 6

    【样例输出】

    13

    3

    36

    源代码:
    
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    struct Node
    {
        int S,To,Next;
    }Edge[80001];
    int m,n,Num(0),i[40001],Deep[40001],Head[40001],f[40001][22];
    void Add(int t1,int t2,int t)
    {
        Edge[++Num].To=t2;
        Edge[Num].S=t;
        Edge[Num].Next=Head[t1];
        Head[t1]=Num;
    }
    void DFS(int T,int S)
    {
        Deep[T]=S;
        for (int a=Head[T];a;a=Edge[a].Next)
        {
            int t=Edge[a].To;
            if (!Deep[t]&&t!=1)
            {
                f[t][0]=T;
                i[t]=i[T]+Edge[a].S;
                DFS(t,S+1);
            }
        }
    }
    void Get_Father()
    {
        for (int b=1;b<=21;b++)
          for (int a=1;a<=n;a++)
            f[a][b]=f[f[a][b-1]][b-1];
    }
    int Get_Same(int T,int S)
    {
        for (int a=0;a<=21;a++)
          if ((1<<a)&S)
            T=f[T][a];
        return T;
    }
    int LCA(int t1,int t2)
    {
        if (t1==1||t2==1)
          return 1;
        if (Deep[t1]<Deep[t2])
          swap(t1,t2);
        t1=Get_Same(t1,Deep[t1]-Deep[t2]);
        if (t1==t2)
          return t1;
        for (int a=21;a>=0;a--)
          if (f[t1][a]!=f[t2][a])
          {
            t1=f[t1][a];
            t2=f[t2][a];
          }
        return f[t1][0];
    }
    int main() //裸倍增LCA。
    {
        scanf("%d%d",&n,&m);
        for (int a=0;a<m;a++)
        {
            char T;
            int t,t1,t2;
            scanf("%d%d%d %c",&t1,&t2,&t,&T);
            Add(t1,t2,t);
            Add(t2,t1,t);
        }
        i[1]=0;
        DFS(1,0);
        Get_Father();
        scanf("%d",&m);
        for (int a=0;a<m;a++)
        {
            int t1,t2;
            scanf("%d%d",&t1,&t2);
            int Ans=LCA(t1,t2);
            printf("%d
    ",i[t1]+i[t2]-(i[Ans]<<1));
        }
        return 0;
    }
  • 相关阅读:
    POJ C程序设计进阶 编程题#4:Tomorrow never knows?
    POJ C程序设计进阶 编程题#3: 发票统计
    深度学习笔记(10)- 控制中心之电源管理、鼠标和触控板、键盘和语言
    深度学习笔记(09)- 控制中心之时间设置
    深度学习笔记(08)- 控制中心之网络设置
    深度学习笔记(07)- 控制中心之声音设置
    深度学习笔记(06)- 控制中心之个性化设置
    深度学习笔记(05)- 控制中心之显示与默认程序
    深度学习笔记(04)- 控制中心之首页与用户管理
    深度学习笔记(03)- 启动器
  • 原文地址:https://www.cnblogs.com/Ackermann/p/5804684.html
Copyright © 2011-2022 走看看