zoukankan      html  css  js  c++  java
  • Codeforces Gym 100015C City Driving 离线LCA

    City Driving

    题目连接:

    http://codeforces.com/gym/100015/attachments

    Description

    You recently started frequenting San Francisco in your free time and realized that driving in the city is a
    huge pain. There are only N locations in the city that interest you, though, and you have decidedtotry
    to improve your driving experience. Since you lack a GPS and cannot remember too many di!erent routes,
    you wrote down the directions and how long it takes to get between N di!erent pairs of locations (the same
    in both directions), ensuring that using only these paths you can get from any location to any other one.
    Now you are planning your trip for the weekend and you need to figureoutthefastestwaytogetbetween
    Q pairs of locations in the city using only the routes you have written down.

    Input

    The input consists of multiple test cases. The first line contains a single integer N,3 ! N ! 100,000, the
    number of locations of interest and the number of routes you wrotedown.Thenext N lines each contain
    three integers u, v,and w (1 ! w ! 1,000), indicating that you have directions from location u to location v
    and vice-versa (0-indexed) which take w time. The following line contains a single integer Q,1 ! Q ! 10,000,
    the number of pairs of locations you need to compute the travel timefor. Thenext Q lines each contain
    two integers u and v, indicating that you should find the minimum time to get from location u to location
    v. The input terminates with a line with N = 0. For example:

    Output

    For each test case, print out Q lines, one for each pair of locations u and v you are finding the fastest routes
    for. Each line should simply contain the minimum time it takes to travel from location u to location v.For
    example, the correct output for the sample input above would be:

    Sample Input

    7

    0 1 2

    0 2 3

    1 3 2

    2 3 8

    2 4 3

    3 5 1

    1 6 7

    3

    4 5

    0 6

    1 2

    0

    Sample Output

    11

    9

    5

    Hint

    题意

    给你一个n环n边的图,问你两点之间的最短路

    题解:

    随便找一个环,然后在这个环上随便去掉一条边,然后就比较这个树上的距离小,还是经过这条边的饿距离小

    比如你去掉的边是a,b,边权是w,你查询u,v

    那么你比较dis(u,v),dis(u,a)+w+dis(b,v),dis(u,b)+w+dis(a,u)就好了

    找环上的边,我推荐用并查集

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 100005
    struct node
    {
        int x,y;
    };
    vector<node>G[maxn];
    int dp[18][maxn*2],dis[maxn],parent[maxn],vis[maxn],pos[maxn],res[maxn];
    int n,m,c,num,cnt,si;
    int qx=0,qy=0,qv=0;
    void init()
    {
        qx = qy = qv = 0;
        cnt = num = si = 0;
        memset(dp,0,sizeof(dp));
        memset(dis,0,sizeof(dis));
        memset(vis,0,sizeof(vis));
        memset(res,0,sizeof(res));
        memset(pos,0,sizeof(pos));
        for(int i=0;i<maxn;i++)
            G[i].clear();
    }
    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;
    }
    
    void dfs3(int u,int dist)
    {
        int i,j;
        vis[u]=1;
        dis[u]=dist;
        pos[u]=cnt;
        res[si]=u;
        dp[0][cnt++]=si++;
        for(i=0;i<G[u].size();i++)
        {
            j=G[u][i].x;
            if(!vis[j])
            {
                dfs3(j,dist+G[u][i].y);
                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)swap(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 main()
    {
        while(scanf("%d",&n)!=EOF)
        {
            if(n==0)break;
            init();
            for(int i=0;i<=n;i++)
                parent[i]=i;
            for(int i=1;i<=n;i++)
            {
                int x,y,z;scanf("%d%d%d",&x,&y,&z);
                x++,y++;
                int p = Find(x),q = Find(y);
                if(p==q){
                    qx = x,qy = y,qv = z;
                    continue;
                }
                Union(x,y);
                G[x].push_back((node){y,z});
                G[y].push_back((node){x,z});
            }
            for(int i=1;i<=n;i++)
                if(!vis[i])
                    dfs3(i,0);
            n=n*2-1;
            rmq();
            int q;
            scanf("%d",&q);
            while(q--)
            {
                int x,y;scanf("%d%d",&x,&y);
                x++,y++;
                int res = Dis(x,y);
                res = min(res,Dis(x,qx)+Dis(y,qy)+qv);
                res = min(res,Dis(x,qy)+Dis(y,qx)+qv);
                printf("%d
    ",res);
            }
        }
    }
  • 相关阅读:
    推荐:负采样
    JNDI学习总结(一)——JNDI数据源的配置
    前端性能优化
    java中的引用类型概念
    java中的各种数据类型在内存中存储的方式
    POI导出EXCEL经典实现
    synchronized 与 Lock 的那点事
    黑马程序员_Map<K,V> 映射关系 Map.Entry
    Java ConcurrentModificationException异常问题
    表 (list)
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5136261.html
Copyright © 2011-2022 走看看