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\n",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\n",ans);
79 }
80 return 0;
81 }