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\n",dis[x]+dis[y]-2*dis[l]);//dis
    }
    return 0;
}
时间: 2024-10-23 10:03:45

usaco feb04距离咨询的相关文章

COGS——T1588. [USACO FEB04]距离咨询

http://cogs.pro/cogs/problem/problem.php?pid=1588 ★★   输入文件:dquery.in   输出文件:dquery.out   简单对比时间限制:1 s   内存限制:256 MB [题目描述] 农夫约翰有N(2<=N<=40000)个农场,标号1到N.M(2<=M<=40000)条的不同的垂直或水平的道路连结着农场,道路的长度不超过1000.这些农场的分布就像下面的地图一样,图中农场用F1..F7表示: 每个农场最多能在东西南北

BZOJ 3364: [Usaco2004 Feb]Distance Queries 距离咨询

Description 一棵树,询问两点间距离. Sol 倍增. 方向没用. 没有然后了. Code /************************************************************** Problem: 3364 User: BeiYu Language: C++ Result: Accepted Time:400 ms Memory:11556 kb **************************************************

[SinGuLaRiTy] 树链问题

[SinGuLaRiTy-1035] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 关于树链 树链是什么?这个乍一看似乎很陌生的词汇表达的其实就是在一棵树中从一个节点到另外一个节点的路径.在许多看似复杂的图论问题中,我们实际上只要对其进行适当的处理,把图转化为一棵树,问题就会得到化简,再运用树链的相关思想就可以较为轻松地解决. 树上倍增 所谓的“树上倍增”,其实就是一种记录节点的方法.我们定义一个数组f[i][j],表示节点i的第2^j

USACO 6.5 Closed Fences

Closed Fences A closed fence in the plane is a set of non-crossing, connected line segments with N corners (3 < N < 200). The corners or vertices are each distinct and are listed in counter-clockwise order in an array {xi, yi}, i in (1..N). Every pa

【USACO 2.1】Hamming Codes

/* TASK: hamming LANG: C++ URL:http://train.usaco.org/usacoprob2?a=5FomsUyB0cP&S=hamming SOLVE: 找粗一个值最小的n个元素的集合,每个元素都是不超过m位二进制的数,且两两之间二进制位不同的位不小于d. dfs,枚举每一个数,枚举范围:(前一个数,1<<m),每次进入dfs都判断一下当前集合是否满足两两距离不小于d. */ #include<cstdio> int n,m,d; in

bzoj usaco 金组水题题解(1)

UPD:我真不是想骗访问量TAT..一开始没注意总长度写着写着网页崩了王仓(其实中午的时候就时常开始卡了= =)....损失了2h(幸好长一点的都单独开了一篇)....吓得赶紧分成两坨....TAT.............. —————————————————————————————————————————————————————————————————————————————— 写(被虐)了整整一个月b站上usaco的金组题...然而到现在总共只写了100道上下TAT(当然是按AC人数降序排

USACO 2013 Nov Silver Pogo-Cow

最近因为闲的蛋疼(停课了),所以开始做一些 USACO 的银组题.被完虐啊 TAT 貌似 Pogo-Cow 这题是 2013 Nov Silver 唯一一道可说的题目? ? Pogo-Cow Description (大意是一条直线上有一些带权值的点,可以选择一个点作为出发点,选好一个前进方向(左或右)然后不断地向前跳到另一个点,得分为这个点的权值,要求每一跳的跳跃距离不小于前一跳,求能获得的最大得分) In an ill-conceived attempt to enhance the mob

USACO hamming 继续暴搜

USER: Kevin Samuel [kevin_s1] TASK: hamming LANG: C++ Compiling... Compile: OK Executing... Test 1: TEST OK [0.003 secs, 3504 KB] Test 2: TEST OK [0.005 secs, 3504 KB] Test 3: TEST OK [0.008 secs, 3504 KB] Test 4: TEST OK [0.008 secs, 3504 KB] Test 5

TYVJ P1081 最近距离 Label:这不是分治!!!

描述 在一块地上,有着n(1<=n<=2000) 头牛,输入n,再分别输入这n头牛的坐标(x,y) (1<=x<=100000,1<=y<=100000),如果第i头牛与第j头牛间的距离最近,那么输出i和j 10 | . . . . . . . 3 . . . . .                     9 | . 1 . . 2 . . . . . . . .                     8 | . . . . . . . . . . . . .