Sichuan State Programming Contest 2012 - Journey

22 篇文章 0 订阅
21 篇文章 0 订阅

题目链接:http://acm.uestc.edu.cn/#/problem/show/92


Journey

Time Limit: 15000/3000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)

Bob has traveled to byteland, he find the N

cities in byteland formed a tree structure, a tree structureis 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 Bobhas Q journey plan, give you the start city and destination city, please tell Bob how many time is savedby 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 ), indicatingthe number of cities in byteland and the journey plans. Then N line followed, each line will contain threeinteger x , y ( 1x,yN ) and z ( 1z1000 ) indicating there is a road cost z time connectthe 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 twointeger 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 and output

Sample InputSample Output
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
Case #1:
0
2
0
2
2

题意是给一棵树,然后在树上再加入一条边,问加入边之后询问的a b两点间的路程减少了多少


对于所有的点,我们可以分为环上的点和非环上的点组成

而非环上的点减少的路程是有它们在环上的父亲节点缩短的路程决定的

即A B缩短的距离 是 F[A] F[B]缩短的距离

而对于环上的点,我们可以指定新加入的XY边上的Y点为相对点

求出没有加入最后一条边时,所有点到  Y点的距离 Li

加入最后一条边后  我们找出环上的点  其中必然包括Y点  此时,Y点为环上点组成的树(不包括最后一条边)的根节点,而任意两点u v的距离则为 ans1= |Lu-Lv|

然后对与环上的点  求出加入最后一条边后到Y的新距离  即Y点此时只能与X点相连,不能与另一点X`相连

求出新的距离NewLi  则加入边后环上点到Y点的距离为 ans2= |NewLU-NewLv|

那么  缩短的路程就为 ans1-ans2>0?(ans1-ans2):0


#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;

const int N=1e5+50;

struct node
{
    int u,v,w,next;
} e[N*2],ee[N];

int tol,head[N];
int lenx[N],leny[N];
int pre[N];
int newy[N];
int flag[N],hah[N];
int n,m;
int x,y,len;

void add(int u,int v,int w)
{
    e[tol].u=u;
    e[tol].v=v;
    e[tol].w=w;
    e[tol].next=head[u];
    head[u]=tol++;
    e[tol].v=u;
    e[tol].u=v;
    e[tol].w=w;
    e[tol].next=head[v];
    head[v]=tol++;
}

void bfs()
{
    queue<int >q;
    q.push(y);
    memset(leny,-1,sizeof(leny));
    memset(lenx,-1,sizeof(lenx));
    leny[y]=0;
    newy[y]=0;
    lenx[x]=0;
    while(q.size())
    {
        int st=q.front();
        q.pop();
        for(int i=head[st]; i!=-1; i=e[i].next)
        {
            int v=e[i].v;
            if(v==st) continue ;
            if(leny[v]==-1)
            {
                leny[v]=leny[st]+e[i].w;
                newy[v]=leny[v];
                q.push(v);
            }
        }
    }
    q.push(x);
    while(q.size())
    {
        int st=q.front();
        q.pop();
        for(int i=head[st]; i!=-1; i=e[i].next)
        {
            int v=e[i].v;
            if(v==st) continue ;
            if(lenx[v]==-1)
            {
                lenx[v]=lenx[st]+e[i].w;
                q.push(v);
            }
        }
    }

}

void bfs_huan()
{
    memset(flag,-1,sizeof(flag));
    queue<int>q;
    q.push(x);
    while(q.size())
    {
        int st=q.front();
        q.pop();
        for(int i=head[st]; i!=-1; i=e[i].next)
        {
            int v=e[i].v;
            if(v==pre[st]) continue ;
            if(pre[v]==-1)
            {
                pre[v]=st;
                q.push(v);
            }
            else
            {
                int vv=v;
                int pp=st;
                while(vv!=-1)
                {
                    vv=pre[vv];
                    pre[v] = pp;
                    pp=v;
                    v=vv;
                }
                flag[x]=1;
                hah[1]=x;
                int l=2;
                for(int j=pre[x]; j!=x; j=pre[j])
                {
                    hah[l]=j;
                    flag[j]=l++;
                }
                return ;
            }
        }
    }
}

void bfs_newy()
{
    queue<int>q;
    q.push(y);
    newy[y]=0;
    while(q.size())
    {
        int st=q.front();
        q.pop();
        for(int i=head[st];i!=-1;i=e[i].next)
        {
            int v=e[i].v;
            if(flag[v]==-1) continue ;
            if(newy[v]>newy[st]+e[i].w)
            {
                newy[v]=newy[st]+e[i].w;
                q.push(v);
            }
        }
    }
}

void bfs_flag()
{
    queue<int>q;
    for(int i=1;i<=n;i++)
        if(flag[i]!=-1)
            q.push(i);

    while(q.size())
    {
        int st=q.front();
        q.pop();
        for(int i=head[st];i!=-1;i=e[i].next)
        {
            int v=e[i].v;
            if(flag[v]==-1)
            {
                flag[v]=flag[st];
                q.push(v);
            }
        }
    }
}

int main()
{
    int t,tt=1;
    scanf("%d",&t);
    while(t--)
    {
        printf("Case #%d:\n",tt++);
        tol=0;
        memset(head,-1,sizeof(head));
        memset(pre,-1,sizeof(pre));
        scanf("%d%d",&n,&m);
        for(int i=0; i<n-1; i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
        }
        scanf("%d%d%d",&x,&y,&len);
        bfs();
        add(x,n+1,len);
        add(y,n+1,0);
        newy[n+1]=len+10;
        bfs_huan();
        bfs_newy();
        bfs_flag();
        for(int i=0;i<m;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            if(flag[a]==flag[b])
            {
                printf("0\n");
                continue ;
            }
            else
            {
                a=hah[flag[a]];
                b=hah[flag[b]];
                int len1=leny[a]-leny[b];
                if(len1<0) len1=-len1;
                int len2=newy[a]+newy[b];
                //cout<<leny[a]<<"*"<<newy[a]<<endl;

               // cout<<leny[b]<<"*"<<newy[b]<<endl;
                len1=(len1-len2)>0?(len1-len2):(0);
                printf("%d\n",len1);
            }
        }
    }

    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值