Codevs 2370 小机房的树

时间限制: 1 s  空间限制: 256000 KB   题目等级 : 钻石 Diamond
题目描述 Description

小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上。有一天,他们想爬到一个节点上去搞基,但是作为两只虫子,他们不想花费太多精力。已知从某个节点爬到其父亲节点要花费 c 的能量(从父亲节点爬到此节点也相同),他们想找出一条花费精力最短的路,以使得搞基的时候精力旺盛,他们找到你要你设计一个程序来找到这条路,要求你告诉他们最少需要花费多少精力

输入描述 Input Description
第一行一个n,接下来n-1行每一行有三个整数u,v, c 。表示节点 u 爬到节点 v 需要花费 c 的精力。
第n+1行有一个整数m表示有m次询问。接下来m行每一行有两个整数 u ,v 表示两只虫子所在的节点
输出描述 Output Description

一共有m行,每一行一个整数,表示对于该次询问所得出的最短距离。

样例输入 Sample Input

3

1 0 1

2 0 1

3

1 0

2 0

1 2

样例输出 Sample Output

1

1

2

数据范围及提示 Data Size & Hint

1<=n<=50000, 1<=m<=75000, 0<=c<=1000

50分WA代码:

 1 #include<cstring>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<iostream>
 5 using namespace std;
 6 #define maxn 60010
 7 #define S 16
 8 int n,m,a[maxn],deep[maxn],fa[maxn][S+10],ans,p1,p2,head[maxn],num,dis[maxn];
 9 struct node{
10     int u,v,pre,value;//  dis[i] 数组 从 i到根节点的最短距离 
11 }e[maxn*2];
12 void dfs(int u,int di)
13 {
14     dis[u]=di;/*统计u到根节点的距离*/
15     for(int l=head[u];l;l=e[l].pre)
16     {
17         if(!deep[e[l].v])
18         {
19             deep[e[l].v]=deep[u]+1;/*处理孩子的深度*/
20             fa[e[l].v][0]=u;/*初始化p数组*/
21             dfs(e[l].v,di+e[l].value);
22         }
23     }
24 }
25 void get_fa()
26 {
27     for(int j=1;j<=S;j++)
28         for(int i=1;i<=n;i++)
29             fa[i][j]=fa[fa[i][j-1]][j-1];
30 }
31 int LCA(int a,int b)
32 {
33     if(deep[a]<deep[b])swap(a,b); 
34     for(int j=S;j>=0;j--)
35       if((deep[a]-(1<<j))>=deep[b])
36         a=fa[a][j];
37     if(a==b)return a;
38     for(int i=S;i>=0;i--)
39       if(fa[a][i]!=fa[b][i])
40         {
41           a=fa[a][i];
42           b=fa[b][i];
43         }
44     return fa[a][0];
45 }
46 void add_egre(int from,int to,int value)
47 {
48     num++;
49     e[num].u=from;
50     e[num].v=to;
51     e[num].value=value;
52     e[num].pre=head[from];
53     head[from]=num;
54 }
55 int main()
56 {
57     scanf("%d",&n);
58     for(int i=1,x,y,z;i<n;i++)
59     {
60         scanf("%d%d%d",&x,&y,&z);
61         add_egre(x,y,z);add_egre(y,x,z);
62     }
63     memset(dis,0,sizeof(dis));
64     memset(deep,0,sizeof(deep));
65     dfs(1,0);
66     get_fa();scanf("%d",&m);
67     for(int i=1;i<=m;i++)
68     {
69         scanf("%d%d",&p1,&p2);
70         int k=LCA(p1,p2);
71         ans=dis[p1]+dis[p2]-2*dis[k];// deep shendu
72         printf("%d
",ans);
73     }
74     return 0;
75 }

赶脚思路没毛病~~~

AC代码:

 1 #include<cstring>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<iostream>
 5 using namespace std;
 6 #define maxn 60010
 7 #define S 16
 8 int n,m,a[maxn],deep[maxn],fa[maxn][20],ans,p1,p2,head[maxn],num;long long dis[maxn];
 9 struct node{
10     int u,v,pre,value;//  dis[i] 数组 从 i到根节点的最短距离 
11 }e[maxn*4];
12 void dfs(int u,long long di)
13 {
14     dis[u]=di;/*处理u到根节点的距离*/
15     for(int l=head[u];l;l=e[l].pre)
16     {
17         if(!deep[e[l].v])
18         {
19             deep[e[l].v]=deep[u]+1;/*处理孩子的深度*/
20             fa[e[l].v][0]=u;/*初始化fa数组*/
21             dfs(e[l].v,di+e[l].value);
22         }
23     }
24 }
25 int LCA(int a,int b)
26 {
27     int i,j;
28     if(deep[a]<deep[b]) swap(a,b); 
29     for(i=0;(1<<i)<=deep[a];++i);
30          i--;
31     for(j=i;j>=0;j--)
32       if((deep[a]-(1<<j))>=deep[b])
33         a=fa[a][j];
34     if(a==b)return a;
35     for(j=i;j>=0;j--)
36       if(fa[a][j]!=-1&&fa[a][j]!=fa[b][j])
37         {
38           a=fa[a][j];
39           b=fa[b][j];
40         }
41     return fa[a][0];
42 }
43 void init()
44 {
45      int i,j;
46      for(j=1;(1<<j)<n;j++)
47        for(int i=0;i<n;++i)
48         if(fa[i][j]=-1)
49           fa[i][j]=fa[fa[i][j-1]][j-1];/*DP处理出i的所有2^j祖先是谁*/
50 }
51 void add_egre(int from,int to,int value)
52 {
53     num++;
54     e[num].u=from;
55     e[num].v=to;
56     e[num].value=value;
57     e[num].pre=head[from];
58     head[from]=num;
59 }
60 int main()
61 {
62     scanf("%d",&n);
63     for(int i=1,x,y,z;i<n;i++)
64     {
65         scanf("%d%d%d",&x,&y,&z);
66         add_egre(x,y,z);add_egre(y,x,z);
67     }
68     memset(fa,-1,sizeof(fa));
69     deep[0]=0;
70     dfs(0,0);
71     init(); 
72     scanf("%d",&m);
73     for(int i=1;i<=m;i++)
74     {
75         scanf("%d%d",&p1,&p2);
76         int k=LCA(p1,p2);
77         ans=dis[p1]+dis[p2]-2*dis[k];
78         printf("%d
",ans);
79     }
80     return 0;
81 }
原文地址:https://www.cnblogs.com/suishiguang/p/6103739.html