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)
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
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.
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 }