题目大意是:对于(n, m)的图,给定边a, b查询从a到b要经过的割点的最少数目。

先tarjan算法求双连通然后缩点,即对于每个割点将周围的每个双连通看成一个点与之相连。然后求解LCA即可,距离dis[u]表示从根出发到u的遍历过程中经过的割顶的数目,利用

tarjan离线算法, 最后答案是:dis[u] + dis[v] - 2*dis[findset(v)] + (findset(v) > bcc_cnt)。注意findset(v) > bcc_cnt表示当LCA(u,v) 为割顶时的判断,此时必须加1。

代码:

  1. #include <iostream>
  2. #include <sstream>
  3. #include <cstdio>
  4. #include <climits>
  5. #include <cstring>
  6. #include <cstdlib>
  7. #include <string>
  8. #include <stack>
  9. #include <map>
  10. #include <cmath>
  11. #include <vector>
  12. #include <queue>
  13. #include <algorithm>
  14. #define esp 1e-6
  15. #define pi acos(-1.0)
  16. #define pb push_back
  17. #define lson l, m, rt<<1
  18. #define rson m+1, r, rt<<1|1
  19. #define mp(a, b) make_pair((a), (b))
  20. #define in freopen("in.txt", "r", stdin);
  21. #define out freopen("out.txt", "w", stdout);
  22. #define print(a) printf("%d\n",(a));
  23. #define bug puts("********))))))");
  24. #define stop system("pause");
  25. #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
  26. #define inf 0x0f0f0f0f
  27.  
  28. using namespace std;
  29. typedef long long LL;
  30. typedef vector<int> VI;
  31. typedef pair<int, int> pii;
  32. typedef vector<pii> VII;
  33. typedef vector<pii, int> VIII;
  34. typedef VI:: iterator IT;
  35. #define eid first
  36. #define vtx second
  37.  
  38. const int maxn = + ;
  39. const int maxm = + ;
  40. int pre[maxn], low[maxn], bccno[maxn], ebccno[maxm], iscut[maxn], vis[maxm], ans[maxn], pa[maxn], bcc_cnt, dfs_clock;
  41. VI g[maxn], bcc[maxn];
  42. VII adj[maxn], query[maxn];
  43. struct edge{
  44. int u, v;
  45. } ee[maxm];
  46. stack<int> S;
  47.  
  48. int dfs(int u, int fa)
  49. {
  50. int lowu = pre[u] = ++dfs_clock;
  51. int child = ;
  52. for(int i = ; i < adj[u].size(); i++)
  53. {
  54. int v = adj[u][i].vtx;
  55. if(!pre[v])
  56. {
  57. S.push(adj[u][i].eid);
  58. child++;
  59. vis[adj[u][i].eid] = ;
  60. int lowv = dfs(v, u);
  61. lowu = min(lowu, lowv);
  62. if(lowv >= pre[u])
  63. {
  64. iscut[u] = ;
  65. bcc_cnt++;
  66. bcc[bcc_cnt].clear();
  67. for(;;)
  68. {
  69. int e = S.top(); S.pop();
  70. bcc[bcc_cnt].pb(e);
  71. ebccno[e] = bcc_cnt;
  72. bccno[ee[e].u] = bccno[ee[e].v] = bcc_cnt;
  73. if(e == adj[u][i].eid) break;
  74. }
  75. }
  76. }
  77. else if(pre[v] < pre[u])
  78. {
  79. if(v != fa)
  80. {
  81. lowu = min(lowu, pre[v]);
  82. S.push(adj[u][i].eid);
  83. vis[adj[u][i].eid] = ;
  84. }
  85. else {
  86. if( !vis[adj[u][i].eid])
  87. {
  88. lowu = min(lowu, pre[v]);
  89. S.push(adj[u][i].eid);
  90. vis[adj[u][i].eid] = ;
  91. }
  92. }
  93. }
  94. }
  95. if(fa < && child == )
  96. {
  97. iscut[u] = ;
  98. }
  99. return low[u] = lowu;
  100. }
  101. void find_bcc(int n)
  102. {
  103. memset(pre, , sizeof(pre));
  104. memset(bccno, , sizeof(bccno));
  105. memset(iscut, , sizeof(iscut));
  106. memset(ebccno, , sizeof(ebccno));
  107. memset(vis, , sizeof(vis));
  108.  
  109. while(!S.empty()) S.pop();
  110. dfs_clock = bcc_cnt = ;
  111. for(int i = ; i < n ;i++)
  112. if(!pre[i])
  113. dfs(i, -);
  114. }
  115. int flag[maxn];
  116. int dis[maxn];
  117. int vv[maxn];
  118. int findset(int x)
  119. {
  120. return pa[x] == x ? x : pa[x] = findset(pa[x]);
  121. }
  122. void tarjan(int u, int d)
  123. {
  124. vv[u] = ;
  125. dis[u] = d;
  126. pa[u] = u;
  127. if(u > bcc_cnt)
  128. dis[u]++;
  129. for(int i = ; i < query[u].size(); i++)
  130. {
  131. int v = query[u][i].first;
  132. int id = query[u][i].second;
  133. if(vis[v])
  134. ans[id] = dis[u] + dis[v] - *dis[findset(v)] + (findset(v) > bcc_cnt);
  135. }
  136. for(int i = ; i < g[u].size(); i++)
  137. {
  138. int v = g[u][i];
  139. if(!vv[v])
  140. {
  141. tarjan(v, dis[u]);
  142. pa[v] = u;
  143. }
  144. }
  145. }
  146. int main(void)
  147. {
  148. int n, m;
  149. while(scanf("%d%d", &n, &m), n||m)
  150. {
  151. for(int i = ; i < maxn; i++)
  152. adj[i].clear(), g[i].clear(), query[i].clear();
  153. memset(flag, -, sizeof(flag));
  154. for(int i = ; i <= m; i++)
  155. {
  156. int u, v;
  157. scanf("%d%d", &u, &v);
  158. u--, v--;
  159. adj[u].pb(mp(i, v));
  160. adj[v].pb(mp(i, u));
  161. ee[i].u = u, ee[i].v = v;
  162. }
  163. find_bcc(n);
  164. int cut_cnt = ;
  165. for(int i = ; i < n; i++)
  166. if(iscut[i])
  167. {
  168. cut_cnt++;
  169. int u = cut_cnt+bcc_cnt;
  170. for(int k = ; k < adj[i].size(); k++)
  171. {
  172. int v = ebccno[adj[i][k].first];
  173. if(flag[v] != u )
  174. {
  175. flag[v] = u;
  176. g[v].pb(u);
  177. g[u].pb(v);
  178. }
  179. }
  180. }
  181. int q;
  182. for(int i = scanf("%d", &q); i <= q; i++)
  183. {
  184. int s, t;
  185. scanf("%d%d", &s, &t);
  186. s = ebccno[s], t = ebccno[t];
  187. query[s].pb(mp(t, i));
  188. query[t].pb(mp(s, i));
  189. }
  190. memset(vv, , sizeof(vv));
  191. for(int i = ; i <= bcc_cnt+cut_cnt; i++)
  192. if(!vv[i])
  193. tarjan(i, );
  194. for(int i = ; i <= q; i++)
  195. printf("%d\n", ans[i]);
  196. }
  197. return ;
  198. }

这个也可用Sparse  Table(ST算法)结合RMQ求解LCA

下面是代码:

  1. #include <iostream>
  2. #include <sstream>
  3. #include <cstdio>
  4. #include <climits>
  5. #include <cstring>
  6. #include <cstdlib>
  7. #include <string>
  8. #include <stack>
  9. #include <map>
  10. #include <cmath>
  11. #include <vector>
  12. #include <queue>
  13. #include <algorithm>
  14. #define esp 1e-6
  15. #define pi acos(-1.0)
  16. #define pb push_back
  17. #define lson l, m, rt<<1
  18. #define rson m+1, r, rt<<1|1
  19. #define mp(a, b) make_pair((a), (b))
  20. #define in freopen("in.txt", "r", stdin);
  21. #define out freopen("out.txt", "w", stdout);
  22. #define print(a) printf("%d\n",(a));
  23. #define bug puts("********))))))");
  24. #define stop system("pause");
  25. #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
  26. #define inf 0x0f0f0f0f
  27.  
  28. using namespace std;
  29. typedef long long LL;
  30. typedef vector<int> VI;
  31. typedef pair<int, int> pii;
  32. typedef vector<pii> VII;
  33. typedef vector<pii, int> VIII;
  34. typedef VI:: iterator IT;
  35. #define eid first
  36. #define vtx second
  37.  
  38. const int maxn = + ;
  39. const int maxm = + ;
  40. int pre[maxn], low[maxn], bccno[maxn], ebccno[maxm], iscut[maxn], vis[maxm], ans[maxn], pa[maxn], bcc_cnt, dfs_clock;
  41. int dep[maxn], E[maxn], R[maxn];
  42. int dp[maxn*][];
  43. VI g[maxn], bcc[maxn];
  44. VII adj[maxn], query[maxn];
  45. struct edge
  46. {
  47. int u, v;
  48. } ee[maxm];
  49. stack<int> S;
  50. int cnt;
  51. int dfs(int u, int fa)
  52. {
  53. int lowu = pre[u] = ++dfs_clock;
  54. int child = ;
  55. for(int i = ; i < adj[u].size(); i++)
  56. {
  57. int v = adj[u][i].vtx;
  58. if(!pre[v])
  59. {
  60. S.push(adj[u][i].eid);
  61. child++;
  62. vis[adj[u][i].eid] = ;
  63. int lowv = dfs(v, u);
  64. lowu = min(lowu, lowv);
  65. if(lowv >= pre[u])
  66. {
  67. iscut[u] = ;
  68. bcc_cnt++;
  69. bcc[bcc_cnt].clear();
  70. for(;;)
  71. {
  72. int e = S.top();
  73. S.pop();
  74. bcc[bcc_cnt].pb(e);
  75. ebccno[e] = bcc_cnt;
  76. bccno[ee[e].u] = bccno[ee[e].v] = bcc_cnt;
  77. if(e == adj[u][i].eid) break;
  78. }
  79. }
  80. }
  81. else if(pre[v] < pre[u])
  82. {
  83. if(v != fa)
  84. {
  85. lowu = min(lowu, pre[v]);
  86. S.push(adj[u][i].eid);
  87. vis[adj[u][i].eid] = ;
  88. }
  89. else
  90. {
  91. if( !vis[adj[u][i].eid])
  92. {
  93. lowu = min(lowu, pre[v]);
  94. S.push(adj[u][i].eid);
  95. vis[adj[u][i].eid] = ;
  96. }
  97. }
  98. }
  99. }
  100. if(fa < && child == )
  101. {
  102. iscut[u] = ;
  103. }
  104. return low[u] = lowu;
  105. }
  106. void find_bcc(int n)
  107. {
  108. memset(pre, , sizeof(pre));
  109. memset(bccno, , sizeof(bccno));
  110. memset(iscut, , sizeof(iscut));
  111. memset(ebccno, , sizeof(ebccno));
  112. memset(vis, , sizeof(vis));
  113.  
  114. while(!S.empty()) S.pop();
  115. dfs_clock = bcc_cnt = ;
  116. for(int i = ; i < n ; i++)
  117. if(!pre[i])
  118. dfs(i, -);
  119. }
  120. int flag[maxn];
  121. int dis[maxn];
  122. int vv[maxn];
  123. int findset(int x)
  124. {
  125. return pa[x] == x ? x : pa[x] = findset(pa[x]);
  126. }
  127. void ST(int u, int d, int sum)
  128. {
  129. vv[u] = ;
  130. R[u] = ++cnt;
  131. dep[cnt] = d;
  132. E[cnt] = u;
  133. dis[u] = sum;
  134. if(u > bcc_cnt)
  135. dis[u]++;
  136. for(int i = ; i < g[u].size(); i++)
  137. {
  138. int v = g[u][i];
  139. if(!vv[v])
  140. {
  141. ST(v, d+, dis[u]);
  142. E[++cnt] = u;
  143. dep[cnt] = d;
  144. }
  145. }
  146. }
  147. void Init(void)
  148. {
  149. for(int i = ; i <= cnt; i++)
  150. dp[i][] = i;
  151. for(int j = ; j <= (int)(log(cnt)/log(2.0)); j++)
  152. for(int i = ; i + (<<j) - <= cnt; i++)
  153. {
  154. if(dep[dp[i][j-]] < dep[dp[i+(<<(j-))][j-]])
  155. dp[i][j] = dp[i][j-];
  156. else dp[i][j] = dp[i + (<<(j-))][j-];
  157. }
  158. }
  159. int RMQ(int u, int v)
  160. {
  161. int k = (int)(log(v - u + )/log(2.0));
  162. if(dep[dp[u][k]] < dep[dp[v - (<<k) + ][k]])
  163. return dp[u][k];
  164. return dp[v - (<<k) + ][k];
  165. }
  166. int main(void)
  167. {
  168.  
  169. int n, m;
  170. while(scanf("%d%d", &n, &m), n||m)
  171. {
  172. for(int i = ; i < maxn; i++)
  173. adj[i].clear(), g[i].clear(), query[i].clear();
  174. memset(flag, -, sizeof(flag));
  175. for(int i = ; i <= m; i++)
  176. {
  177. int u, v;
  178. scanf("%d%d", &u, &v);
  179. u--, v--;
  180. adj[u].pb(mp(i, v));
  181. adj[v].pb(mp(i, u));
  182. ee[i].u = u, ee[i].v = v;
  183. }
  184. find_bcc(n);
  185. int cut_cnt = ;
  186. for(int i = ; i < n; i++)
  187. if(iscut[i])
  188. {
  189. cut_cnt++;
  190. int u = cut_cnt+bcc_cnt;
  191. for(int k = ; k < adj[i].size(); k++)
  192. {
  193. int v = ebccno[adj[i][k].first];
  194. if(flag[v] != u )
  195. {
  196. flag[v] = u;
  197. g[v].pb(u);
  198. g[u].pb(v);
  199. }
  200. }
  201. }
  202. memset(vv, , sizeof(vv));
  203. cnt = ;
  204. for(int i = ; i <= bcc_cnt+cut_cnt; i++)
  205. if(!vv[i])
  206. ST(i, , );
  207. int q;
  208. Init();//记得初始化啊 。。。。。。。。
  209. for(int i = scanf("%d", &q); i <= q; i++)
  210. {
  211. int s, t;
  212. scanf("%d%d", &s, &t);
  213. s = ebccno[s], t = ebccno[t];
  214. int ss , tt;
  215. ss = min(R[s], R[t]);
  216. tt = max(R[s], R[t]);
  217. int lca = RMQ(ss, tt);
  218. lca = E[lca];
  219. int ans = dis[s] + dis[t] - * dis[lca] + (lca > bcc_cnt);
  220. printf("%d\n", ans);
  221. }
  222. }
  223. return ;
  224. }

两者时间上差不多,而且ST算法需要初始化,更容易出错

HDU Traffic Real Time Query System的更多相关文章

  1. HDU 3686 Traffic Real Time Query System (图论)

    HDU 3686 Traffic Real Time Query System 题目大意 给一个N个点M条边的无向图,然后有Q个询问X,Y,问第X边到第Y边必需要经过的点有多少个. solution ...

  2. CH#24C 逃不掉的路 和 HDU3686 Traffic Real Time Query System

    逃不掉的路 CH Round #24 - 三体杯 Round #1 题目描述 现代社会,路是必不可少的.任意两个城镇都有路相连,而且往往不止一条.但有些路连年被各种XXOO,走着很不爽.按理说条条大路 ...

  3. HDU 3686 Traffic Real Time Query System(双连通分量缩点+LCA)(2010 Asia Hangzhou Regional Contest)

    Problem Description City C is really a nightmare of all drivers for its traffic jams. To solve the t ...

  4. HDU3686 Traffic Real Time Query System 题解

    题目 City C is really a nightmare of all drivers for its traffic jams. To solve the traffic problem, t ...

  5. Traffic Real Time Query System 圆方树+LCA

    题目描述 City C is really a nightmare of all drivers for its traffic jams. To solve the traffic problem, ...

  6. hdu 3686 Traffic Real Time Query System 点双两通分量 + LCA。这题有重边!!!

    http://acm.hdu.edu.cn/showproblem.php?pid=3686 我要把这题记录下来. 一直wa. 自己生成数据都是AC的.现在还是wa.留坑. 我感觉我现在倒下去床上就能 ...

  7. Traffic Real Time Query System HDU - 3686

    https://vjudge.net/problem/HDU-3686 点双啊,就是在求割顶的时候,另外用一个栈来存一些边 在遍历u点出发的边时,遇到树边或反向边(u,v)就把此边加入栈(可能要记一下 ...

  8. HDU 3686 Traffic Real Time Query System(点双连通)

    题意 ​ 给定一张 \(n\) 个点 \(m\) 条边的无向图,\(q\) 次询问,每次询问两边之间的必经之点个数. 思路 ​ 求两点之间必经之边的个数用的是边双缩点,再求树上距离.而对比边双和点双之 ...

  9. UVALive-4839 HDU-3686 Traffic Real Time Query System 题解

    题目大意: 有一张无向连通图,问从一条边走到另一条边必定要经过的点有几个. 思路: 先用tarjan将双连通分量都并起来,剩下的再将割点独立出来,建成一棵树,之后记录每个点到根有几个割点,再用RMQ求 ...

随机推荐

  1. MySQL flush privileges 명령어

    INSERT나 UPDATE, DELETE문을 이용해서 MySQL의 사용자를 추가,삭제하거나, 사용자 권한 등을 변경하였을 때, MySQL에 변경사항을 적용하기 위해서 사용하는 명령 ...

  2. 【MINA】序列化和反序列化我们要考虑的问题

    概念 序列化:将java对象转换为字节序列的过程叫做序列化 反序列化:将字节对象转换为java对象的过程叫做反序列化 要解决的问题 1.序列化时间 2.反序列化时间 3.bytes大小 4.操作方便 ...

  3. 本地缓存下载文件,download的二次封装

    来源:http://ask.dcloud.net.cn/article/524 源码下载链接 说明: (1)由于平时项目中大量用到了附件下载等功能,所以就花了一个时间,把plus的downlaod进行 ...

  4. SQLSERVER2000以上 Ad Hoc Distributed Queries的启用与关闭

    SQLSERVER2000以上的版本在查询分析器中查询ACCESS数据时提示:“ 訊息 15281,層級 16,狀態 1,行 1SQL Server 已封鎖元件 'Ad Hoc Distributed ...

  5. CS0016: 未能写入输出文件“c:\windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\data\34aae060\b7daa87d\App_Web_addadvice.aspx.cdcab7d2.ekhlcbjd.dll”--“目录名无效。 ”

    产生原因: 应用程序运行时产生的临时文件需要存放到c:"windows"temp 文件夹下 而运行基于microsoft .net framework 框架下的应用程序 需要对te ...

  6. ASP.NET Web Service如何工作(1)

    ASP.NET Web Service如何工作(1) [日期:2003-06-26] 来源:CSDN  作者:sunnyzhao(翻译) [字体:大 中 小] Summary ASP.NET Web ...

  7. 10_控制线程_线程让步yield

    [线程让步yield()方法] yield()方法可以让当前正在执行的线程暂停,但它不会阻塞该线程,它只是将该线程从运行状态转入就绪状态. 只是让当前的线程暂停一下,让系统的线程调度器重新调度一次. ...

  8. KMP入门(周期)

    Description Given two strings a and b we define a*b to be their concatenation. For example, if a = & ...

  9. Wix: Show conditional message box

    For example: Scenario: Show message box only during installation and MYPROPERTY has to be equal to & ...

  10. 安装kali之后

    更新源(以下设置均基于这些源) #vi /etc/apt/sources.list 把这些源加进去 ############################ debian wheezy ####### ...