zoukankan      html  css  js  c++  java
  • 2018.7中石油个人赛第4场(D-Transit Tree Path)-最短路算法

    6690: Transit Tree Path

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 472  解决: 132
    [提交] [状态] [讨论版] [命题人:admin]

    题目描述

    You are given a tree with N vertices.
    Here, a tree is a kind of graph, and more specifically, a connected undirected graph with N−1 edges, where N is the number of its vertices.
    The i-th edge (1≤i≤N−1) connects Vertices ai and bi, and has a length of ci.

    You are also given Q queries and an integer K. In the j-th query (1≤j≤Q):

    find the length of the shortest path from Vertex xj and Vertex yj via Vertex K.
    Constraints
    3≤N≤105
    1≤ai,bi≤N(1≤i≤N−1)
    1≤ci≤109(1≤i≤N−1)
    The given graph is a tree.
    1≤Q≤105
    1≤K≤N
    1≤xj,yj≤N(1≤j≤Q)
    xj≠yj(1≤j≤Q)
    xj≠K,yj≠K(1≤j≤Q)

    输入

    Input is given from Standard Input in the following format:
    N  
    a1 b1 c1  
    :  
    aN−1 bN−1 cN−1
    Q K
    x1 y1
    :  
    xQ yQ
     

    输出

    Print the responses to the queries in Q lines.
    In the j-th line j(1≤j≤Q), print the response to the j-th query.

    样例输入

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

    样例输出

    3
    2
    4
    

    提示

    The shortest paths for the three queries are as follows:
    Query 1: Vertex 2 → Vertex 1 → Vertex 2 → Vertex 4 : Length 1+1+1=3
    Query 2: Vertex 2 → Vertex 1 → Vertex 3 : Length 1+1=2
    Query 3: Vertex 4 → Vertex 2 → Vertex 1 → Vertex 3 → Vertex 5 : Length 1+1+1+1=4

      1 /*
      2 题意 : 
      3     求结点x经过结点k到达结点y的最短距离
      4     转化为以k结点为起始点,求k分别到结点x和结点y的最短距离
      5     用到SPFA算法
      6 */
      7 //赛后补题,一开始将dist[]的值赋值为INF,wa了
      8 //后来想了一下,INF值为1061109567
      9 //虽然大于1e9,但时如果两条边都是1e9,则加和就>INF,此时就会出错
     10 //所以需要用LINF来个dist[]中的数组初始化为无穷大
     11 //一定要判断清除用哪个
     12 #include<iostream>
     13 #include<cstdio>
     14 #include<cstring>
     15 #include<queue>
     16 #include<vector>
     17 using namespace std;
     18 #define INF 0x3f3f3f3f
     19 #define LINF 0x3f3f3f3f3f3f3f3f
     20 const int maxn=1e5+1;
     21 typedef long long type_weight;
     22 struct Edge
     23 {
     24     //根据题意定义weight的类型
     25     //可能为long long 型,也可能为int型
     26     //用typedef定义type_weight,方便修改类型
     27     int vex;
     28     type_weight weight;
     29     Edge(int v=0,type_weight w=0):vex(v),weight(w){}
     30 };
     31 vector<Edge>E[maxn];
     32 
     33 //向E[u]中加入(v,weight) : 边u与边v相连,其权值为weight
     34 void addedge(int u,int v,type_weight weight)
     35 {
     36     E[u].push_back(Edge(v,weight));
     37 }
     38 //visited[i] : 判断结点i是否在队列中
     39 //dist[] : 存储最短距离,最好定义成long long 型
     40 //cnt[] : 判断是否存在负环
     41 bool visited[maxn];
     42 long long dist[maxn];
     43 int cnt[maxn];
     44 //求从start结点到其他结点的最短距离
     45 //共n个结点
     46 bool SPFA(int start,int n)
     47 {
     48     memset(visited,0,sizeof(visited));
     49     //初始化dist[]为LINF,即长整型的最大值(无穷大)
     50     for(int i=1;i<=n;i++)
     51         dist[i]=LINF;
     52     dist[start]=0;
     53     visited[start]=true;
     54 
     55     queue<int >que;
     56     while(!que.empty())
     57         que.pop();
     58     que.push(start);
     59 
     60     while(!que.empty())
     61     {
     62         int u=que.front();
     63         que.pop();
     64 
     65         //遍历以u为弧尾的所有结点
     66         //E[u][i].v : 以u为弧尾的结点
     67         //E[u][i].weight : 结点u与结点E[u][i].v之间的权重
     68         for(int i=0;i<E[u].size();i++)
     69         {
     70             int v=E[u][i].vex;
     71 
     72             //判断边u是否能松弛边v
     73             if(dist[v] > dist[u]+E[u][i].weight)
     74             {
     75                 dist[v]=dist[u]+E[u][i].weight;
     76                 if(!visited[v])
     77                 {
     78                     que.push(v);
     79                     visited[v]=true;
     80                     //如果某个结点进入队列的此数超过n-1次,则此图存在负环
     81                     if(++cnt[v] > n)
     82                         return false;
     83                 }
     84             }
     85         }
     86     }
     87     return true;
     88 }
     89 
     90 int main()
     91 {
     92     int N;
     93     scanf("%d",&N);
     94     for(int i=1;i<N;i++)
     95     {
     96         int a,b;
     97         type_weight weight;
     98         scanf("%d%d%lld",&a,&b,&weight);
     99         addedge(a,b,weight);
    100         addedge(b,a,weight);
    101     }
    102     int Q,K;
    103     scanf("%d%d",&Q,&K);
    104     SPFA(K,N);
    105     for(int i=1;i<=Q;i++)
    106     {
    107         int x,y;
    108         scanf("%d%d",&x,&y);
    109         printf("%lld
    ",dist[x]+dist[y]);
    110     }
    111     return 0;
    112 }
  • 相关阅读:
    Android手势(上,下,左和右的判断)
    我爱意甲
    程序员特有的9个坏习惯
    我爱英超
    VS2010快捷键总结(一)
    C#中导出Excel总结
    MessageDAL
    GDI+ 绘图总结
    .net中绑定日期时,只显示年月日的做法
    Vb线程控制
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/9364284.html
Copyright © 2011-2022 走看看