CDOJ 1437 谭松松的旅游计划 Label:倍增LCA && 最短路

谭松松的旅游计划

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
Submit Status

谭松松是一个爱旅游的人,他非常的热爱旅游,即便身体被掏空也要坚持旅游。喵蛤王国由N个城市组成,由N-1条道路连通,每条道路长度为ci,使得任意两座城市都能相互到达。谭松松有M个旅游计划,每个旅游计划有一个起点ai,一个终点bi,所以谭松松想知道,对于每个旅游计划,从起点到终点的最短路长度为多少?

Input

第一行两个整数N(2≤N≤100000,),M(1≤M≤100000),表示城市个数,谭松松的旅游计划个数。

接下来N-1行,每行三个整数li,ri,ci(1≤ci≤10000),表示li号城市和ri号城市之间有一条长度为ci的道路。

接下来M行,每行两个整数ai,bi表示旅游计划的起点和终点。

Output

输出M行,表示每个旅游计划的最短距离。

Sample input and output

Sample InputSample Output
7 6
1 2 5
1 3 4
3 7 7
2 4 4
2 5 3
5 6 2
1 2
4 7
6 3
3 2
5 4
7 6
5
20
14
9
7
21 

 

代码

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<queue>
 7 #define ll long long
 8 const int MAXN=200005;
 9 using namespace std;
10 
11 int N,M;
12 int pa[30][MAXN],depth[MAXN],vis[MAXN];
13 ll cost[30][MAXN];//注意long long 
14 vector<int> G[MAXN],c[MAXN];
15 
16 void dfs(int x,int pre,int d){
17     vis[x]=1;
18     depth[x]=d;
19     pa[0][x]=pre;
20     for(int i=0;i<G[x].size();i++){
21         int to=G[x][i];
22         if(!vis[to]){
23             cost[0][to]=c[x][i];
24             dfs(to,x,d+1);
25         }
26     }
27 }
28 
29 void init_lca(){
30     memset(pa,-1,sizeof(pa));
31     
32     dfs(1,-1,0);
33     for(int k=0;k<=25;k++){
34         for(int i=1;i<=N;i++){
35             if(pa[k][i]>0){
36                 pa[k+1][i]=pa[k][ pa[k][i] ];
37                 cost[k+1][i]=cost[k][i]+cost[k][ pa[k][i] ];
38 //                cout<<cost[k+1][i]<<endl;
39             }
40         }
41     }
42 }
43 
44 ll lca(int u,int v){//long long
45     ll sum=0;
46     if(depth[u]>depth[v]) swap(u,v);
47 //    cout<<u<<v<<endl;
48     for(int k=0;k<25;k++){
49         if((depth[v]-depth[u])>>k&1){
50             sum+=cost[k][v];
51             v=pa[k][v];//这两行不能换..... 
52 //            cout<<cost[k][u]<<endl;
53         }
54     }
55     
56     if(u==v) return sum;
57     for(int k=25;k>=0;k--){
58         if(pa[k][u]!=pa[k][v]){
59             sum+=(cost[k][u]+cost[k][v]);
60             u=pa[k][u];
61             v=pa[k][v];
62         }
63     }
64     sum+=(cost[0][v]+cost[0][u]);
65     return sum;
66 }
67 
68 int main(){
69 //    freopen("01.in","r",stdin);
70     scanf("%d%d",&N,&M);
71     for(int i=1;i<N;i++){
72         int x,y,cc;
73         scanf("%d%d%d",&x,&y,&cc);
74         G[x].push_back(y);
75         G[y].push_back(x);
76         c[x].push_back(cc);
77         c[y].push_back(cc);
78     }
79     init_lca();
80     while(M--){
81         int a,b;
82         scanf("%d%d",&a,&b);
83         printf("%lld\n",lca(a,b));//此处用cout会T!!! 
84     }
85     return 0;
86 }

Line50 和Line51换了会爆炸

然后83用cout会爆炸,直接T掉

 

输出1万次就得用printf

cout也就比printf慢几千倍吧~

 

转载于:https://www.cnblogs.com/radiumlrb/p/5929006.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值