• usaco feb04距离咨询


    [USACO FEB04]距离咨询

    成绩   开启时间 2014年09月19日 星期五 10:08
    折扣 0.8 折扣时间 2014年09月26日 星期五 10:08
    允许迟交 关闭时间 2014年09月26日 星期五 10:08
    输入文件 dquery.in 输出文件 dquery.out

    【题目描述】

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

    每个农场最多能在东西南北四个方向连结4个不同的农场。此外,农场只处在道路的两端。道路不会交叉而且每对农场间有且仅有一条路径。邻居鲍伯要约翰来导航,但约翰丢了农场的地图,他只得从电脑的备份中修复率。每一条道路的信息如下:

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

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

        . . .

    最近美国过度肥胖非常普遍。农夫约翰为了让他的奶牛多做运动,举办了奶牛马拉松。马拉松路线要尽量长。

    奶牛们拒绝跑马拉松,因为她们悠闲的生活无法承受约翰选择的如此长的赛道。因此约翰决心找一条更合理的赛道。他打算咨询你。读入地图之后会有K个问题,每个问题包括2个整数,就是约翰感兴趣的2个农场的编号,请尽快算出这2个农场间的距离。

    【输入格式】

    第1行:两个分开的整数N和M。

    第2到M+1行:每行包括4个分开的内容,F1,F2,L,D分别描述两个农场的编号,道路的长度,F1到F2的方向N,E,S,W。

    第2+M行:一个整数K(1<=K<=10000).

    第3+M到2+M+K行:每行输入2个整数,代表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

    【提示】

    农场2到农场6有20+3+13=36的距离。

    【来源】

    Brian Dean,2004

    USACO 2004 February Contest Green Problem 3 Distance Queries

    Translate by: 庄乐

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define MAXN 80001
    #define D 20
    using namespace std;
    int n,m,head[MAXN],tot,cut,dis[MAXN],k;
    //dis[i]表示1到i的距离.路是不相交的所以没有最长最短之分. 
    int fa[MAXN][D+5],deep[MAXN];//fa[i][j]表示i点的向上2^j是什么.
    //deep[i]表示i在树中的深度. 
    struct data{int v,next,x;}e[MAXN];
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
        return x*f;
    }
    void dfs(int now,int f,int d)//dfs序建树. 
    {
        deep[now]=d;fa[now][0]=f;
        for(int i=head[now];i;i=e[i].next)
        {
            if(e[i].v!=f)
            {
                dis[e[i].v]=dis[now]+e[i].x;//dis连边更新 
                dfs(e[i].v,now,d+1);
            }
        }
    }
    void add(int u,int v,int z)
    {
        e[++tot].v=v;
        e[tot].x=z;
        e[tot].next=head[u];
        head[u]=tot;
    }
    void get_father()//二进制找father. 
    {
        for(int j=1;j<=20;j++)
          for(int i=1;i<=n;i++)
            fa[i][j]=fa[fa[i][j-1]][j-1];
            //dis[i][j]=max(dis[i][j-1],dis[fa[i][j-1]][j-1]);
    }
    int get_same(int u,int v)
    {
        for(int i=0;i<=20;i++)
          if((1<<i)&v) u=fa[u][i];
        return u;
    }
    int lca(int u,int v)//lca. 
    {
        if(u==1||v==1) return 1;
        if(deep[u]<deep[v]) swap(u,v);
        u=get_same(u,deep[u]-deep[v]);
        if(u==v) return u;
        for(int i=20;i>=0;i--)//找lca的儿子. 
          if(fa[u][i]!=fa[v][i])
            u=fa[u][i],v=fa[v][i];
        //ans+=dis[u][0];ans+=dis[v][0];
        return fa[u][0];//再往上蹦一层. 
    }
    int main()
    {
        freopen("dquery.in","r",stdin);
        freopen("dquery.out","w",stdout);
        int x,y,z;
        n=read(),m=read();
        for(int i=1;i<=m;i++)
        {
            x=read(),y=read(),z=read();
            add(x,y,z),add(y,x,z);
        }
        dfs(1,0,0);
        get_father();
        k=read();
        for(int i=1;i<=k;i++)
        {
            x=read(),y=read();
            int l=lca(x,y);
            printf("%d
    ",dis[x]+dis[y]-2*dis[l]);//dis 
        }
        return 0;
    }
  • 相关阅读:
    sql 2008查看进程情况和对应语句,检查死锁进程
    sqlserver2008锁表语句详解(锁定数据库一个表)
    sqlserver 中的时间算法
    SQL server 2008 数据库优化常用脚本
    Win7下64位机安装SQL2000
    Git回退到服务器某个版本正确姿势
    一个有趣的倒计时问题
    如何申请AWS免费ACM
    AWS账号、用户、服务之间的关系
    [RDL]中多行组列组占比报表制作
  • 原文地址:https://www.cnblogs.com/xiaoningmeng/p/5808109.html
Copyright © 2020-2023  润新知