cdoj 92 Journey tarjan/lca 树上点对距离

Journey

Time Limit: 1 Sec  

Memory Limit: 256 MB

题目连接

http://acm.uestc.edu.cn/#/problem/show/92

Description

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 N1 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(1T20), indicating there are T test cases.

For each test case, the first will line contain two integers N(2N105) and Q(1Q105), indicating the number of cities in byteland and the journey plans. Then N line followed, each line will contain three integer xy(1x,yN) and z(1z1000) indicating there is a road cost z time connect the xth city and the yth city, the first N1 roads will form a tree structure, indicating the original roads, and the Nth line is the road built after Bob advised the king. Then Q line followed, each line will contain two integer x and y(1x,yN), indicating there is a journey plan from the xth city to yth 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 ith line contains one integer indicating the time could saved in ith journey plan.

Sample Input

1
5 5
1 2 3
2 3 4
4 1 5
3 5 1
3 1 5
1 2
1 3
2 5
3 4
4 5
 

Sample Output

Case #1:
0
2
0
2
2

HINT

 

题意

给你一棵树,然后加了一条边,然后给Q次询问,问你这些点之间的最短距离缩短了多少

题解:

加了边之后,你走的方式就变成三种了,要么和原来一样,要么就是u-A-B-v,要么就是u-B-A-v这种

tarjan预处理一下距离跑一发就好了

代码:

//qscqesze
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <bitset>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
//freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define maxn 200006
#define mod 1000000007
#define eps 1e-9
#define e exp(1.0)
#define PI acos(-1)
const double EP  = 1E-10 ;
int Num;
//const int inf=0x7fffffff;
const ll inf=999999999;
inline ll read()
{
    ll 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-'0';ch=getchar();}
    return x*f;
}
//***********************************************************
struct ndoe{
    int v,w,next;
}ed[maxn*2];
int dp[18][maxn*2],pos[maxn],dis[maxn],res[maxn],head[maxn],parent[maxn],vis[maxn];
int n,m,c,num,cnt,size;
void addedge(int u,int v,int w)
{
    ed[num].v=v;
    ed[num].w=w;
    ed[num].next=head[u];
    head[u]=num++;
}
int Find(int i)
{
    if(i!=parent[i])
        parent[i]=Find(parent[i]);
    return parent[i];
}
void Union(int i,int j)
{
    int x,y;
    x=Find(i);
    y=Find(j);
    if(x!=y)
        parent[x]=y;
}
int A,B,C,q;
void init()
{
    int i,j,k;
    n=read();q=read();
    m=n-1;
    memset(head,-1,sizeof(head));
    memset(vis,0,sizeof(vis));
    for(i=0;i<=n;i++)
        parent[i]=i;
    cnt=size=num=0;
    while(m--)
    {
        scanf("%d%d%d",&i,&j,&k);
        addedge(i,j,k);
        addedge(j,i,k);
        Union(i,j);
    }
    A=read(),B=read(),C=read();
}
void dfs(int u,int dist)
{
    int i,j;
    vis[u]=1;
    dis[u]=dist;
    pos[u]=cnt;
    res[size]=u;
    dp[0][cnt++]=size++;
    for(i=head[u];i!=-1;i=ed[i].next)
    {
        j=ed[i].v;
        if(!vis[j])
        {
            dfs(j,dist+ed[i].w);
            dp[0][cnt++]=dp[0][pos[u]];
        }
    }
}
void rmq()
{
    int i,j,k;
    for(i=1;(1<<i)<=n;i++)
        for(j=n-1;j>=0;j--)
        {
            k=(1<<(i-1));
            dp[i][j]=dp[i-1][j];
            if(k+j<n)
                dp[i][j]=min(dp[i][j],dp[i-1][j+k]);
        }
}
int cal(int i,int j)
{
    int k;
    if(i<j)
    {
        i^=j;
        j^=i;
        i^=j;
    }
    k=0;
    while((1<<k)<=(i-j+1))
        k++;
    k--;
    k=min(dp[k][j],dp[k][i-(1<<k)+1]);
    return res[k];
}
int Dis(int u,int v)
{
    int k = cal(pos[u],pos[v]);
    return dis[u]+dis[v]-dis[k]*2;
}
int tot = 0;
void solve()
{
    int i,j,k;
    for(i=1;i<=n;i++)
        if(!vis[i])
            dfs(i,0);
    n=n*2-1;
    rmq();
    printf("Case #%d:\n",tot);
    for(int i=1;i<=q;i++)
    {
        int u=read(),v=read();
        int P = Dis(u,v);
        int PP1 = Dis(u,A)+C+Dis(B,v);
        int PP2 = Dis(u,B)+C+Dis(A,v);
        PP1 = min(PP1,PP2);
        printf("%d\n",max(P-PP1,0));
    }
}
int main()
{
    int t=read();
    while(t--)
    {
        tot++;
        init();
        solve();
    }
    return 0;
}

 

posted @ 2015-09-24 20:30  qscqesze  阅读(486)  评论(0编辑  收藏  举报