http://codeforces.com/gym/100676/attachments

题目大意:

有n个城市,有m条路,每条路都有边长,如果某几个城市的路能组成一个环,那么在环中的这些城市就有传送门,能够瞬间抵达对方的城市(即距离为0),否则,就要走这条路,并且经过的路程为这条路的长度。

问,找一个城市作为这些城市的首都

要求:除了首都城市外,其他城市到首都的最大距离最短。

思路:

边双连通缩点以后就是一棵树,找树上的直径,首都一定是直径上的点。(orz,自己明明注意到了一定是直径上面的点,在之前的好多次的wa中却忘了是要找直径上的点了)

  1. //看看会不会爆int!数组会不会少了一维!
  2. //取物问题一定要小心先手胜利的条件
  3. #include <bits/stdc++.h>
  4. using namespace std;
  5. #pragma comment(linker,"/STACK:102400000,102400000")
  6. #define LL long long
  7. #define ALL(a) a.begin(), a.end()
  8. #define pb push_back
  9. #define mk make_pair
  10. #define fi first
  11. #define se second
  12. #define haha printf("haha\n")
  13. /*
  14. 思路:
  15. 双连通缩点,然后随便找一个点树dp,
  16. 树dp,距离最短的肯定就是直径上的某一个点
  17. */
  18. const int maxn = 1e5 + ;
  19. const int maxm = 2e5 + ;
  20. const LL inf = 1e17;
  21. vector<pair<int, LL> > G[maxn];
  22. int n, m;
  23. /*****************/
  24. int dfstime, bcccnt;
  25. bool iscut[maxn];
  26. int bccnu[maxn], pre[maxn];
  27. stack<int> s;
  28. vector<int> bcc[maxn];
  29.  
  30. int dfs(int u, int fa){
  31. int lowu = pre[u] = ++dfstime;
  32. int len = G[u].size();
  33. int child = ;
  34. s.push(u);
  35. for (int i = ; i < len; i++){
  36. int v = G[u][i].fi;
  37. if (pre[v] == -){
  38. child++;
  39. int lowv = dfs(v, u);
  40. lowu = min(lowv, lowu);
  41. if (lowv > pre[u]){
  42. iscut[u] = true;
  43. }
  44. }
  45. else if (pre[v] < pre[u] && v != fa){
  46. lowu = min(lowu, pre[v]);
  47. }
  48. }
  49. if (lowu == pre[u]){
  50. bcccnt++;
  51. while (true){///边双连通分量是不存在重点的
  52. int v = s.top(); s.pop();
  53. bccnu[v] = bcccnt;
  54. bcc[bcccnt].pb(v);
  55. if (v == u) break;
  56. }
  57. }
  58. if (fa == - && child == ) iscut[u] = false;
  59. return lowu;
  60. }
  61.  
  62. void get_connect(){
  63. dfstime = bcccnt = ;
  64. memset(iscut, false, sizeof(iscut));
  65. memset(bccnu, , sizeof(bccnu));
  66. memset(pre, -, sizeof(pre));
  67. dfs(, -);
  68. }
  69.  
  70. vector<pair<int, LL> > new_edge[maxn];
  71. void rebuild(){
  72. ///O(n + m)
  73. for (int i = ; i <= bcccnt; i++){
  74. for (int j = ; j < bcc[i].size(); j++){
  75. int u = bcc[i][j];
  76. for (int k = ; k < G[u].size(); k++){
  77. int v = G[u][k].fi;
  78. LL val = G[u][k].se;
  79. if (bccnu[u] != bccnu[v]){
  80. new_edge[bccnu[u]].push_back(mk(bccnu[v], val));
  81. }
  82. }
  83. }
  84. }
  85. /* printf("bcccnt = %d\n", bcccnt);
  86.  
  87. cout << "new_edge.output" << endl;
  88. for (int i = 1; i <= bcccnt; i++){
  89. for (int j = 0; j < new_edge[i].size(); j++){
  90. printf("u = %d v = %d val = %d\n", i, new_edge[i][j].fi, new_edge[i][j].se);
  91. }
  92. cout << endl;
  93. }
  94. */
  95. }
  96.  
  97. int p; LL maxval;
  98. LL can[maxn];
  99. void dfs1(int u, int fa, LL sum){
  100. if (sum > maxval){
  101. maxval = sum, p = u;
  102. }
  103. for (int i = ; i < new_edge[u].size(); i++){
  104. int v = new_edge[u][i].fi;
  105. LL tmp = new_edge[u][i].se;
  106. if (v == fa) continue;
  107. dfs1(v, u, sum + tmp);
  108. }
  109. }
  110.  
  111. LL d1[maxn], d2[maxn];
  112. ///d1从最底下到目前节点的距离
  113. ///d2表示从根到目前节点的距离
  114. void dfs2(int u, int fa, LL sum){
  115. d2[u] = sum;
  116. for (int i = ; i < new_edge[u].size(); i++){
  117. int v = new_edge[u][i].fi;
  118. LL val = new_edge[u][i].se;
  119. if (v == fa) continue;
  120. dfs2(v, u, sum + val);
  121. d1[u] = max(d1[u], d1[v] + val);
  122. }
  123. }
  124.  
  125. LL mini;
  126. vector<int> ansp;
  127. void dfs3(int u, int fa){
  128. for (int i = ; i < new_edge[u].size(); i++){
  129. int v = new_edge[u][i].fi;
  130. LL val = new_edge[u][i].se;
  131. if (v == fa) continue;
  132. if (d1[u] - val == d1[v]){
  133. dfs3(v, u);
  134. LL tmp = max(d1[u], d2[u]);
  135. if (mini > tmp){
  136. ansp.clear(); mini = tmp; ansp.pb(u);
  137. }
  138. else if (mini == tmp){
  139. ansp.pb(u);
  140. }
  141. }
  142. }
  143. }
  144.  
  145. int main(){
  146. int t; cin >> t;
  147. while (t--){
  148. scanf("%d%d", &n, &m);
  149. for (int i = ; i <= n; i++){
  150. G[i].clear(); bcc[i].clear();
  151. new_edge[i].clear();
  152. }
  153. for (int i = ; i <= m; i++){
  154. int u, v; LL val; scanf("%d%d%lld", &u, &v, &val);
  155. G[u].pb(mk(v, val)); G[v].pb(mk(u, val));
  156. }
  157. get_connect();
  158. rebuild();
  159. p = , maxval = ;
  160. dfs1(, -, );
  161.  
  162. memset(d1, , sizeof(d1));
  163. memset(d2, , sizeof(d2));
  164. ansp.clear();
  165. dfs2(p, -, 0LL);
  166.  
  167. mini = inf;
  168. dfs3(p, -);
  169.  
  170. int ans = n + ;
  171. for (int i = ; i < ansp.size(); i++){
  172. int u = ansp[i];
  173. for (int j = ; j < bcc[u].size(); j++){
  174. ans = min(ans, bcc[u][j]);
  175. }
  176. }
  177. if (ans == n + ) {ans = , mini = ;}
  178. printf("%d %lld\n", ans, mini);
  179. }
  180. return ;
  181. }

边双连通缩点+树dp 2015 ACM Arabella Collegiate Programming Contest的Gym - 100676H的更多相关文章

  1. Codeforces Gym 2015 ACM Arabella Collegiate Programming Contest(二月十日训练赛)

    A(By talker): 题意分析:以a(int) op b(int)形式给出两个整数和操作符, 求两个整数是否存在操作符所给定的关系 ,有则输出true,无则输出false: 思路:由于无时间复杂 ...

  2. 2015 ACM Arabella Collegiate Programming Contest

    题目链接:https://vjudge.net/contest/154238#overview. ABCDE都是水题. F题,一开始分类讨论,结果似乎写挫了,WA了一发.果断换并查集上,A了. G题, ...

  3. gym100676 [小熊骑士限定]2015 ACM Arabella Collegiate Programming Contest

    Kuma Rider久违的第二场训练,这场很水,又在vj的榜单上看到第一场的大哥了,2小时ak,大哥牛啤! A.水 #include<cstdio> #include<iostrea ...

  4. 18春季训练01-3/11 2015 ACM Amman Collegiate Programming Contest

    Solved A Gym 100712A Who Is The Winner Solved B Gym 100712B Rock-Paper-Scissors Solved C Gym 100712C ...

  5. ACM Arabella Collegiate Programming Contest 2015 H. Capital City 边连通分量

    题目链接:http://codeforces.com/gym/100676/attachments 题意: 有 n 个点,m 条边,图中,边强连通分量之间可以直达,即距离为 0 ,找一个点当做首都,其 ...

  6. 2015 ACM Amman Collegiate Programming Contest 题解

    [题目链接] A - Who Is The Winner 模拟. #include <bits/stdc++.h> using namespace std; int T; int n; s ...

  7. 2015 ACM Syrian Collegiate Programming Contest

    A. My Friend of Misery 计算出答案的上下界即可. 时间复杂度$O(n)$. #include<bits/stdc++.h> using namespace std; ...

  8. ACM Arabella Collegiate Programming Contest 2015 F. Palindrome 并查集

    题目链接:http://codeforces.com/gym/100676/attachments 题意: 给一个字符串,有一些约束条件,两个位置要相同,有一些是问号,求最后有多少种方案回文? 分析: ...

  9. ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2017)- K. Poor Ramzi -dp+记忆化搜索

    ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2017)- K. ...

随机推荐

  1. Thunder团队第七周 - Scrum会议3

    Scrum会议3 小组名称:Thunder 项目名称:i阅app Scrum Master:李传康 工作照片: 参会成员: 王航:http://www.cnblogs.com/wangh013/ 李传 ...

  2. 跨域写cookie

    假设a站想往b站写cookie,那么目前有两种方案,参考如下: 第一种(使用jsonp): a站js代码如下: $.ajax({ url: 'http://www.b.com/jsonp.jsp?do ...

  3. 【Leetcode】179. Largest Number

    Given a list of non negative integers, arrange them such that they form the largest number. For exam ...

  4. PAT 甲级 1027 Colors in Mars

    https://pintia.cn/problem-sets/994805342720868352/problems/994805470349344768 People in Mars represe ...

  5. FastReport.Net 无限页高(连续纸小票)

    using System; using System.Collections; using System.Collections.Generic; using System.ComponentMode ...

  6. Java知识点整理(三)

    如何设计出高可用的分布式架构 分布式架构 CDN简介 分布式缓存和本地缓存区别 高并发场景常用技术解决方案 JVM优化示例 Docker和JVM区别 Java开发人员需要注意的五大Docker误区 D ...

  7. 【前端学习笔记01】JavaScript源生判断数据类型的方法

    原始类型(值类型):Undefined.Null.Number.String.Boolean: 对象类型(引用类型):Object: typeof  可以识别标准类型,null外(返回Object): ...

  8. 迭代器 每迭代一次 指针往下面移动一次 除非JVM回收了内存 否则 他的指针不会回到原地

    迭代器 每迭代一次 指针往下面移动一次 除非JVM回收了内存 否则 他的指针不会回到原地

  9. bzoj1923[Sdoi2010]外星千足虫(高斯消元)

    Description Input 第一行是两个正整数 N, M. 接下来 M行,按顺序给出 Charles 这M次使用“点足机”的统计结果.每行 包含一个“01”串和一个数字,用一个空格隔开.“01 ...

  10. 【bzoj3518】点组计数 欧拉函数(欧拉反演)

    题目描述 平面上摆放着一个n*m的点阵(下图所示是一个3*4的点阵).Curimit想知道有多少三点组(a,b,c)满足以a,b,c三点共线.这里a,b,c是不同的3个点,其顺序无关紧要.(即(a,b ...