[关闭]
@Chilling 2017-03-05T11:34:34.000000Z 字数 4389 阅读 865

UESTC-92: Journey(LCA 倍增 | 树剖)

LCA 树链剖分


Description

Bob has traveled to byteland, he find the N cities in byteland formed a tree structure, a tree structure is very special structure, there is exactly one path connecting each pair of nodes, and a tree with N nodes has N−1 edges.
As a traveler, Bob wants to journey between those N cities, and he know the time each road will cost.
He advises the king of byteland building a new road to save time, and then, a new road was built.
Now Bob has Q journey plan, give you the start city and destination city, please tell Bob how many time is saved by add a road if he always choose the shortest path. Note that if it's better not journey from the new roads, the answer is 0.

Input

First line of the input is a single integer , indicating there are T test cases.

For each test case, the first will line contain two integers and , indicating the number of cities in byteland and the journey plans. Then N line followed, each line will contain three integer , and indicating there is a road cost z time connect the city and the city, the first roads will form a tree structure, indicating the original roads, and the line is the road built after Bob advised the king.
Then line followed, each line will contain two integer and , indicating there is a journey plan from the city to city.

Output

For each case, you should first output Case #t: in a single line, where t indicating the case number between 1 and T, then Q lines followed, the line contains one integer indicating the time could saved in journey plan.

Sample Input

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

Sample Output

Case #1:
0 
2 
0 
2 
2

题意: t组数据,有n个点,q次询问,1到n-1行表示最初x到y点距离为z,第n行为新加入的一条边a到b距离为c,每次询问:新加入边之后节省了多少路程,若没有则输出0。

分析:原图两点之间的距离可以用LCA求得,dis[x,y]=dis[x]+dis[y]-2*dis[LCA(x,y)];若要经过新加入的边(a,b,c),起点x,终点y,那么一定有:从x→a,a→b,b→y或者x→b,b→a,a→y;ab间距离为c,其他两段距离用LCA求得。最后与原路程比较即可。


倍增

  1. #include<stdio.h>
  2. #include<vector>
  3. #include<algorithm>
  4. #include<string.h>
  5. const int maxn=1e5+5;
  6. using namespace std;
  7. int n,q;
  8. int dep[maxn],dis[maxn];
  9. int fa[maxn][15];
  10. struct node
  11. {
  12. int en,val;
  13. node(int enn=0,int vall=0)
  14. {
  15. en=enn;
  16. val=vall;
  17. }
  18. };
  19. vector<node> V[maxn];
  20. void clr()
  21. {
  22. memset(dep,0,sizeof(dep));
  23. memset(dis,0,sizeof(dis));
  24. memset(fa,0,sizeof(fa));
  25. for(int i=0;i<=n;i++)
  26. V[i].clear();
  27. }
  28. void dfs(int u,int f,int d)
  29. {
  30. fa[u][0]=f;
  31. for(int i=1;i<15;i++)
  32. fa[u][i]=fa[fa[u][i-1]][i-1];
  33. dep[u]=d;
  34. for(int i=0;i<V[u].size();i++)
  35. {
  36. node v=V[u][i];
  37. if(v.en==f) continue;
  38. dis[v.en]=dis[u]+v.val;
  39. dfs(v.en,u,d+1);
  40. }
  41. }
  42. int LCA(int u,int v)
  43. {
  44. if(dep[u]>dep[v])
  45. swap(u,v);
  46. for(int i=0;i<15;i++)
  47. if((dep[v]-dep[u])>>i&1)
  48. v=fa[v][i];
  49. if(u==v) return u;
  50. for(int i=14;i>=0;i--)
  51. {
  52. if(fa[u][i]!=fa[v][i])
  53. {
  54. u=fa[u][i];
  55. v=fa[v][i];
  56. }
  57. }
  58. return fa[u][0];
  59. }
  60. int main()
  61. {
  62. int t,o=0;
  63. int x,y,z;
  64. int a,b,c;
  65. scanf("%d",&t);
  66. while(t--)
  67. {
  68. clr();
  69. scanf("%d%d",&n,&q);
  70. for(int i=1;i<n;i++)
  71. {
  72. scanf("%d%d%d",&x,&y,&z);
  73. V[x].push_back(node(y,z));
  74. V[y].push_back(node(x,z));
  75. }
  76. dfs(1,0,1);
  77. scanf("%d%d%d",&a,&b,&c);
  78. printf("Case #%d:\n",++o);
  79. while(q--)
  80. {
  81. scanf("%d%d",&x,&y);
  82. int d1=dis[x]+dis[y]-2*dis[LCA(x,y)];
  83. int d2=dis[x]+dis[a]-2*dis[LCA(x,a)]+dis[y]+dis[b]-2*dis[LCA(y,b)]+c;
  84. int d3=dis[x]+dis[b]-2*dis[LCA(x,b)]+dis[y]+dis[a]-2*dis[LCA(y,a)]+c;
  85. d2=min(d2,d3);
  86. printf("%d\n",d1-d2<0?0:d1-d2);
  87. }
  88. }
  89. return 0;
  90. }

树剖求LCA

  1. #include<stdio.h>
  2. #include<vector>
  3. #include<string.h>
  4. #include<algorithm>
  5. using namespace std;
  6. const int maxn=1e5+5;
  7. int n,q;
  8. int dis[maxn];
  9. int siz[maxn],dep[maxn],fa[maxn],son[maxn];
  10. int top[maxn];
  11. struct node
  12. {
  13. int en,val;
  14. node(int enn=0,int vall=0)
  15. {
  16. en=enn;
  17. val=vall;
  18. }
  19. };
  20. vector<node> V[maxn];
  21. void clr()
  22. {
  23. memset(dis,0,sizeof(dis));
  24. memset(dep,0,sizeof(dep));
  25. memset(fa,0,sizeof(fa));
  26. memset(son,0,sizeof(son));
  27. for(int i=0;i<=n;i++)
  28. V[i].clear();
  29. }
  30. void dfs1(int u,int f,int d)
  31. {
  32. dep[u]=d;
  33. fa[u]=f;
  34. siz[u]=1;
  35. for(int i=0;i<V[u].size();i++)
  36. {
  37. node v=V[u][i];
  38. if(v.en==f) continue;
  39. dis[v.en]=dis[u]+v.val;
  40. dfs1(v.en,u,d+1);
  41. if(siz[v.en]>siz[son[u]])
  42. son[u]=v.en;
  43. siz[u]+=siz[v.en];
  44. }
  45. }
  46. void dfs2(int u,int f,int id)
  47. {
  48. top[u]=id;
  49. if(!son[u]) return;
  50. dfs2(son[u],u,id);
  51. for(int i=0;i<V[u].size();i++)
  52. {
  53. node v=V[u][i];
  54. if(v.en==f||v.en==son[u]) continue;
  55. dfs2(v.en,u,v.en);
  56. }
  57. }
  58. int LCA(int u,int v)
  59. {
  60. while(top[u]!=top[v])
  61. {
  62. if(dep[top[u]]<dep[top[v]])
  63. swap(u,v);
  64. u=fa[top[u]];
  65. }
  66. if(dep[u]<dep[v])
  67. swap(u,v);
  68. return v;
  69. }
  70. int main()
  71. {
  72. int t,o=0;
  73. int x,y,z;
  74. int a,b,c;
  75. scanf("%d",&t);
  76. while(t--)
  77. {
  78. clr();
  79. scanf("%d%d",&n,&q);
  80. for(int i=1;i<n;i++)
  81. {
  82. scanf("%d%d%d",&x,&y,&z);
  83. V[x].push_back(node(y,z));
  84. V[y].push_back(node(x,z));
  85. }
  86. dfs1(1,0,1);
  87. dfs2(1,0,1);
  88. scanf("%d%d%d",&a,&b,&c);
  89. printf("Case #%d:\n",++o);
  90. while(q--)
  91. {
  92. scanf("%d%d",&x,&y);
  93. int d1=dis[x]+dis[y]-2*dis[LCA(x,y)];
  94. int d2=dis[x]+dis[a]-2*dis[LCA(x,a)]+dis[y]+dis[b]-2*dis[LCA(y,b)]+c;
  95. int d3=dis[x]+dis[b]-2*dis[LCA(x,b)]+dis[y]+dis[a]-2*dis[LCA(y,a)]+c;
  96. d2=min(d2,d3);
  97. printf("%d\n",d1-d2<0?0:d1-d2);
  98. }
  99. }
  100. return 0;
  101. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注