codevs1519过路费

来源:互联网 发布:听音乐下载什么软件 编辑:程序博客网 时间:2024/04/28 09:25

题目描述 Description

在某个遥远的国家里,有 n个城市。编号为 1,2,3,…,n。这个国家的政府修建了m 条双向道路,每条道路连接着两个城市。政府规定从城市 S 到城市T需要收取的过路费为所经过城市之间道路长度的最大值。如:A到B长度为 2,B到C 长度为3,那么开车从 A经过 B到C 需要上交的过路费为 3。佳佳是个做生意的人,需要经常开车从任意一个城市到另外一个城市,因此他需要频繁地上交过路费,由于忙于做生意,所以他无时间来寻找交过路费最低的行驶路线。然而, 当他交的过路费越多他的心情就变得越糟糕。 作为秘书的你,需要每次根据老板的起止城市,提供给他从开始城市到达目的城市,最少需要上交多少过路费。

输入描述 Input Description

第一行是两个整数 n 和m,分别表示城市的个数以及道路的条数。 接下来 m 行,每行包含三个整数 a,b,w(1≤a,b≤n,0≤w≤10^9),表示a与b之间有一条长度为 w的道路。接着有一行为一个整数 q,表示佳佳发出的询问个数。 再接下来 q行,每一行包含两个整数 S,T(1≤S,T≤n,S≠T), 表示开始城市S 和目的城市T。

输出描述 Output Description

输出共q行,每行一个整数,分别表示每个询问需要上交的最少过路费用。输入数据保证所有的城市都是连通的。

样例输入 Sample Input

4 5 1 2 10 1 3 20 1 4 100 2 4 30 3 4 10 2 1 4 4 1

样例输出 Sample Output

20 20

数据范围及提示 Data Size & Hint

对于 30%的数据,满足 1≤ n≤1000,1≤m≤10000,1≤q≤100; 对于 50%的数据,满足 1≤ n≤10000,1≤m≤10000,1≤q≤10000; 对于 100%的数据,满足 1≤ n≤10000,1≤m≤100000,1≤q≤10000;

分析:

这个题目的话,注意到“政府规定从城市 S 到城市T需要收取的过路费为所经过城市之间道路长度的最大值。”这一句就可以很容易的想到这可以用最小生成树来解,然后求最小值的话,可用倍增来求lca就可以了,具体细节的话看代码

代码

#include <cstdio>#include <algorithm>#include <iostream>using namespace std;struct edge{    int u,v,w;    bool operator < (const edge &h)const{        return w < h.w;    }}a[102000];int fa[12000];int rn[12000][15];int rp[12000][15];int he[12000];int ne[22000];int to[22000];int we[22000];int de[12000];int n,m;int rea();int fin(int);void uni(int,int);void dfs(int,int);int lca(int,int);int main(){    n=rea() , m = rea();    for(int i=1;i<=n;++i)        fa[i] = i;    for(int i=1;i<=m;++i)        a[i].u=rea() , a[i].v=rea() , a[i].w=rea();    sort(a+1,a+m+1);    for(int i=1,k=1,p,q;i<=m&&k<n;++i){        p = fin(a[i].u);        q = fin(a[i].v);        if(p != q){            fa[p] = q;            k++;            ne[k]=he[a[i].u];he[a[i].u]=k;to[k]=a[i].v;we[k]=a[i].w;            ne[k+n]=he[a[i].v];he[a[i].v]=k+n;to[k+n]=a[i].u;we[k+n]=a[i].w;        }    }    de[1] = 1;    dfs(1,-1);    int q = rea();    for(int i=1;i<=q;++i)        printf("%d\n",lca(rea(),rea()));    return 0;}int rea(){    int in = 0;    char ch = getchar();    while(ch>'9' || ch<'0')        ch = getchar();    while(ch>='0' && ch<='9'){        in = in*10+ch-'0';        ch = getchar();    }    return in;}int fin(int x){    int r = x;    while(r != fa[r])        r = fa[r];    int p;    while(x != fa[x]){        p = fa[x];        fa[x] = r;        x = p;    }    return r;}void uni(int x,int y){    fa[fin(x)] = fin(y);}void dfs(int x,int y){    for(int i=he[x];i;i=ne[i])        if(to[i] != y){            rn[to[i]][0] = x;            rp[to[i]][0] = we[i];            de[to[i]] = de[x]+1;            for(int j=1;rn[rn[to[i]][j-1]][j-1];++j){                rn[to[i]][j] = rn[rn[to[i]][j-1]][j-1];                rp[to[i]][j] = max(rp[to[i]][j-1],rp[rn[to[i]][j-1]][j-1]);            }            dfs(to[i],x);        }}int lca(int x,int y){    int ans = 0;    if(de[x] > de[y])        swap(x,y);    int derta = de[y]-de[x];    for(int i=0;(1<<i)<=derta;++i)        if(derta&(1<<i)){            ans = max(ans,rp[y][i]);            y = rn[y][i];        }    if(x == y)        return ans;    for(int i=0;;++i)        if(rn[x][i] == rn[y][i]){            if(i == 0)                return max(ans,max(rp[x][0],rp[y][0]));            else{                ans = max(ans,max(rp[x][i-1],rp[y][i-1]));                x = rn[x][i-1];                y = rn[y][i-1];                i = -1;            }        }}
0 0
原创粉丝点击