[关闭]
@xunuo 2017-02-16T19:42:13.000000Z 字数 2614 阅读 1111

HDU 2874 Connections between cities(倍增)


Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

LCA


Description

After World War X, a lot of cities have been seriously damaged, and we need to rebuild those cities. However, some materials needed can only be produced in certain places. So we need to transport these materials from city to city. For most of roads had been totally destroyed during the war, there might be no path between two cities, no circle exists as well.
Now, your task comes. After giving you the condition of the roads, we want to know if there exists a path between any two cities. If the answer is yes, output the shortest path between them.

Input

Input consists of multiple problem instances.For each instance, first line contains three integers n, m and c, 2<=n<=10000, 0<=m<10000, 1<=c<=1000000. n represents the number of cities numbered from 1 to n. Following m lines, each line has three integers i, j and k, represent a road between city i and city j, with length k. Last c lines, two integers i, j each line, indicates a query of city i and city j.

Output

For each problem instance, one line for each query. If no path between two cities, output “Not connected”, otherwise output the length of the shortest path between them.

Sample Input

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

Sample Output

Not connected
6

题意:

给你一个森林,求两个点之间的距离是多少,如果这两个点没有在同一棵树上则输出"Not connected";
输入表示的意思:
    第一行输入三个n,m,k;表示这个森林有n个点,接下来m行表示各个节点的关系;k表示要查询的k组数据;

解题思路:

如果两个点在同一棵树上,要求他们间的距离就只需要找出他们的最近公共祖先,dis=dis[x]+dis[v]-2*dis[lca(u,v)]就可以了
主要是当u和v不在同意棵树上的时候;
    我们可以用一个数组来存每个节点的根节点,如果它们的根节点相同则他们在同一棵数上,如果不同则不在同一棵树上;

完整代码:

  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<algorithm>
  4. #include<vector>
  5. using namespace std;
  6. #define N 10010
  7. int dep[N];///深度
  8. int p[N][20];///p[i][j]表示i的2^j倍祖先
  9. int dis[N];///距离
  10. int root[N];///存根节点
  11. int n;
  12. struct node
  13. {
  14. int w,l;
  15. node(int ww=0,int ll=0)
  16. {
  17. w=ww;
  18. l=ll;
  19. }
  20. };
  21. vector<node>g[N];
  22. void dfs(int u,int f,int d,int id)///id表示这棵树的根节点
  23. {
  24. dep[u]=d;
  25. p[u][0]=f;
  26. root[u]=id;
  27. for(int i=0;i<g[u].size();i++)
  28. {
  29. int v=g[u][i].w;
  30. if(v==f)
  31. continue;
  32. dis[v]=dis[u]+g[u][i].l;
  33. dfs(v,u,d+1,id);
  34. }
  35. }
  36. void init()
  37. {
  38. for(int j=1;(1<<j)<=n;j++)
  39. for(int i=1;i<=n;i++)
  40. if(p[i][j]!=-1)
  41. p[i][j]=p[p[i][j-1]][j-1];
  42. }
  43. int lca(int u,int v)
  44. {
  45. if(dep[u]>dep[v])
  46. swap(u,v);
  47. int i;
  48. for(i=0;(1<<i)<=dep[v];i++);
  49. for(int j=i-1;j>=0;j--)
  50. if(dep[v]-(1<<j)>=dep[u])
  51. v=p[v][j];
  52. if(u==v)
  53. return u;
  54. for(int j=i-1;j>=0;j--)
  55. {
  56. if(p[v][j]!=-1&&p[u][j]!=p[v][j])
  57. {
  58. u=p[u][j];
  59. v=p[v][j];
  60. }
  61. }
  62. return p[u][0];
  63. }
  64. int main()
  65. {
  66. int m,k;
  67. while(scanf("%d%d%d",&n,&m,&k)!=EOF)
  68. {
  69. int a,b,c;
  70. memset(dis,0,sizeof(dis));
  71. memset(root,0,sizeof(root));
  72. for(int i=0;i<=n;i++)
  73. g[i].clear();
  74. for(int i=0;i<m;i++)
  75. {
  76. scanf("%d%d%d",&a,&b,&c);
  77. g[a].push_back(node(b,c));
  78. g[b].push_back(node(a,c));
  79. }
  80. for(int i=1;i<=n;i++)
  81. if(root[i]==0)
  82. dfs(i,0,0,i);
  83. init();
  84. int x,y;
  85. for(int i=0;i<k;i++)
  86. {
  87. scanf("%d%d",&x,&y);
  88. if(root[x]!=root[y])
  89. printf("Not connected\n");
  90. else
  91. printf("%d\n",dis[x]+dis[y]-2*dis[lca(x,y)]);
  92. }//
  93. }
  94. return 0;
  95. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注