BNU 24258 Journey (LCA)

来源:互联网 发布:访客网络限速多少 编辑:程序博客网 时间:2024/05/21 15:04

Bob has traveled to byteland, he find the N cities in byteland formed a tree structure, a tree structure is very special structure, there is exactly one path connecting each pair of nodes, and a tree with N nodes has N - 1 edges.

As a traveler, Bob wants to journey between those N cities, and he know the time each road will cost. he advises the king of byteland building a new road to save time, and then, a new road was built. Now Bob has Q journey plan, give you the start city and destination city, please tell Bob how many time is saved by add a road if he always choose the shortest path. Note that if it's better not journey from the new roads,
the answer is 0.

Input

First line of the input is a single integer T(1 <= T <= 20), indicating there are T test cases.

For each test case, the first will line contain two integers N(2 <= N <= 10^5) and Q(1 <= Q <= 10^5), indicating the number of cities in byteland and the journey plans. Then N line followed, each line will contain three integer x, y(1 <= x,y <= N) and z(1 <= z <= 1000) indicating there is a road cost z time connect the x-th city and the y-th city, the first N - 1 roads will form a tree structure, indicating the original roads, and the N-th line is the road built after Bob advised the king. Then Q line followed, each line will contain two integer x and y(1 <= x,y <= N), indicating there is a journey plan from the x-th city to y-th city.

Output

For each case, you should first output "Case #t:" in a single line, where t indicating the case number between 1 and T, then Q lines followed, the i-th line contains one integer indicating the time could saved in i-th journey plan.

题意:给出n个结点的树,q次询问,然后给出一条额外添加的边,从a到b距离为c。q次询问,给出u,v,询问uv的最短距离比原来短多少。

思路:按原图建图,然后已b为根求出到其他点的dis,
uv=dis[u]+dis[v]-2*dis[lca(u,v)]; 
tem=min(ua+vb,ub+va)+c; 
ans=max(0,uv-ans);

#include<iostream>#include<cstdio>#include<queue>#include<cstring>using namespace std;#define N 100005struct node{    int u,v,w,next;} e[2*N];int head[N],dis[N],visit[N],pre[N],rrank[N],use[N];int k;void init(){    k=0;    memset(head,-1,sizeof(head));}void add(int u,int v,int w){    e[k].u=u;    e[k].v=v;    e[k].w=w;    e[k].next=head[u];    head[u]=k++;}int fa[N][20],dep[N];void dfs(int u){    use[u]=1;    for(int i=head[u]; i!=-1; i=e[i].next)    {        int v=e[i].v;        if(!use[v])        {            dis[v]=dis[u]+e[i].w;            rrank[v]=rrank[u]+1;            pre[v]=u;            dfs(v);        }    }}/*倍增法求LCA nlogn*/void bfs(int root){    queue<int>q;    dep[root]=0;    fa[root][0]=root;    q.push(root);    while(!q.empty())    {        int u=q.front();        q.pop();        for(int i=1; i<20; i++)            fa[u][i]=fa[fa[u][i-1]][i-1];        for(int i=head[u]; i!=-1; i=e[i].next)        {            int v=e[i].v;            if(v==fa[u][0]) continue;            dep[v]=dep[u]+1;            fa[v][0]=u;            q.push(v);        }    }}int lca(int u,int v){    if(dep[u]>dep[v]) swap(u,v);    int hu=dep[u],hv=dep[v];    int tu=u,tv=v;    for(int det=hv-hu,i=0; det; det>>=1,i++)    {        if(det&1)            tv=fa[tv][i];    }    if(tv==tu) return tu;    for(int i=19; i>=0; i--)    {        if(fa[tu][i]==fa[tv][i]) continue;        tu=fa[tu][i];        tv=fa[tv][i];    }    return fa[tu][0];}int main(){    int T,n,m,i,q,t=1;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&q);        m=n-1;        init();        int u,v,w;        for(i=0; i<m; i++)        {            scanf("%d%d%d",&u,&v,&w);            add(u,v,w);            add(v,u,w);        }        memset(dis,0,sizeof(dis));        memset(pre,0,sizeof(pre));        memset(use,0,sizeof(use));        memset(rrank,0,sizeof(rrank));        memset(dep,0,sizeof(dep));        memset(fa,0,sizeof(fa));        int a,b,c;        scanf("%d%d%d",&a,&b,&c);        dfs(b);//求dis        bfs(b);        printf("Case #%d:\n",t++);        while(q--)        {            scanf("%d%d",&u,&v);            int ua=dis[u]+dis[a]-2*dis[lca(u,a)];            int vb=dis[v];            int ub=dis[u];            int va=dis[v]+dis[a]-2*dis[lca(v,a)];            int uv=dis[u]+dis[v]-2*dis[lca(u,v)];            int ans=min(ua+vb,ub+va)+c;            printf("%d\n",max(0,uv-ans));        }    }}


0 0
原创粉丝点击