链接:https://ac.nowcoder.com/acm/contest/3002/F
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

有一天,maki拿到了一颗树。所谓树,即没有自环、重边和回路的无向连通图。
这个树有 个顶点, 条边。每个顶点被染成了白色或者黑色。
maki想知道,取两个不同的点,它们的简单路径上有且仅有一个黑色点的取法有多少?
注:
①树上两点简单路径指连接两点的最短路。
的取法视为同一种。

 
 
 

输入描述:

  1. 第一行一个正整数n。代表顶点数量。

  1. 第二行是一个仅由字符'B''W'组成的字符串。第 i个字符是B代表第 i 个点是黑色,W代表第 i个点是白色。
  1. 接下来的n-1行,每行两个正整数 x y,代表 x 点和 y点有一条边相连

输出描述:

  1. 一个正整数,表示只经过一个黑色点的路径数量。
示例1

输入

复制

  1. 3
  2. WBW
  3. 1 2
  4. 2 3

输出

复制

  1. 3

说明

树表示如下:
其中只有2号是黑色点。
<1,2>、<2,3>、<1,3>三种取法都只经过一个黑色点。
 
思路:
   对于可以连边的白色节点,用并查集把节点合并,并且在合并时更新连通块大小。
   对于一条含有黑色节点的路径,我们易知:路径数 = 黑色节点相邻的 白连通块内点的size * 该点相连的白连通块点的size···
   
   所以只需要先求出白连通块的大小,然后对于黑点,只需要计算出黑点相邻白连通块加上其的后继连通块即可。
   后继白连通块大小求法:
   

   关于_find中为什么是sum += sz[r2]的问题,因为建的是无向图,不保证此时的fa[r1]一定是与fa[r2]相等的

  

  1. #include <bits/stdc++.h>
  2. #define dbg(x) cout << #x << "=" << x << endl
  3.  
  4. using namespace std;
  5. typedef long long LL;
  6. const int maxn = 1e6 + ;
  7.  
  8. int n;
  9. LL ans;
  10. int fa[maxn];
  11. int a[maxn];
  12. int head[maxn];
  13. char c[maxn];
  14. int cnt = ;
  15. LL sz[maxn];
  16. LL num[maxn];
  17. int _count = ;
  18.  
  19. //vector <int> g[maxn];
  20.  
  21. struct Edge {
  22. int to,nxt;
  23. }edge[maxn];
  24.  
  25. void BuildGraph(int u, int v) {
  26. edge[cnt].to = v;
  27. edge[cnt].nxt = head[u];
  28. head[u] = cnt++;
  29.  
  30. edge[cnt].to = u;
  31. edge[cnt].nxt = head[v];
  32. head[v] = cnt++;
  33. }
  34.  
  35. void init()
  36. {
  37. memset(head, -, sizeof(head));
  38. for(int i = ; i <= n; i++) {
  39. fa[i] = i;
  40. sz[i] = ;
  41. }
  42. }
  43.  
  44. namespace _buff {
  45. const size_t BUFF = << ;
  46. char ibuf[BUFF], *ib = ibuf, *ie = ibuf;
  47. char getc() {
  48. if (ib == ie) {
  49. ib = ibuf;
  50. ie = ibuf + fread(ibuf, , BUFF, stdin);
  51. }
  52. return ib == ie ? - : *ib++;
  53. }
  54. }
  55.  
  56. int read() {
  57. using namespace _buff;
  58. int ret = ;
  59. bool pos = true;
  60. char c = getc();
  61. for (; (c < '' || c > '') && c != '-'; c = getc()) {
  62. assert(~c);
  63. }
  64. if (c == '-') {
  65. pos = false;
  66. c = getc();
  67. }
  68. for (; c >= '' && c <= ''; c = getc()) {
  69. ret = (ret << ) + (ret << ) + (c ^ );
  70. }
  71. return pos ? ret : -ret;
  72. }
  73.  
  74. int fid(int x)
  75. {
  76. int r = x;
  77. while(fa[r] != r) {
  78. r = fa[r];
  79. }
  80. int i,j;///路径压缩
  81. i = x;
  82. while(fa[i] != r) {
  83. j = fa[i];
  84. fa[i] = r;
  85. i = j;
  86. }
  87. return r;
  88. }
  89.  
  90. void join(int r1,int r2)///合并
  91. {
  92. int fidroot1 = fid(r1), fidroot2 = fid(r2);
  93. int root = min(fidroot1, fidroot2);
  94. sz[root] = sz[fidroot1] + sz[fidroot2];
  95. if(fidroot1 != fidroot2) {
  96. fa[fidroot2] = root;
  97. fa[fidroot1] = root;
  98. }
  99. }
  100.  
  101. LL _find(int x) {
  102. //dbg(x);
  103. LL sum = ;
  104. for(int i = head[x]; ~i; i = edge[i].nxt) {
  105. int v = edge[i].to;
  106. if(a[v]) {
  107. //num[v] = 0;
  108. continue;
  109. }
  110. int r1 = fid(x), r2 = fid(v);
  111. sum += sz[r2];
  112. num[++_count] = sz[r2];
  113. }
  114. return sum;
  115. }
  116.  
  117. int main()
  118. {
  119. scanf("%d\n",&n);
  120. init();
  121. ans = ;
  122. scanf("%s",c);
  123. for(int i = ; i < n; ++i) {
  124. if(c[i] == 'W') {
  125. a[i+] = ;
  126. }
  127. else {
  128. a[i+] = ;
  129. }
  130. }
  131. for(int i = ; i < n; ++i) {
  132. int x, y;
  133. scanf("%d %d",&x, &y);
  134. BuildGraph(x,y);
  135. if(!a[x] && !a[y]) {
  136. join(x,y);
  137. }
  138. }
  139. for(int i = ; i <= n; ++i) {
  140. if(a[i] == ) continue;
  141. _count = ;
  142. memset(num, , sizeof(num));
  143. ans += _find(i);
  144. for(int j = ; j <= _count; ++j) {
  145. for(int k = j+; k <= _count; ++k) {
  146. ans += num[j] * num[k];
  147. }
  148. }
  149. }
  150.  
  151. printf("%lld\n",ans);
  152. }
 

2020牛客寒假算法基础集训营1 F-maki和tree的更多相关文章

  1. 2020牛客寒假算法基础集训营2 J题可以回顾回顾

    2020牛客寒假算法基础集训营2 A.做游戏 这是个签到题. #include <cstdio> #include <cstdlib> #include <cstring ...

  2. 2020牛客寒假算法基础集训营1 J题可以回顾回顾

    2020牛客寒假算法基础集训营1 这套题整体来说还是很简单的. A.honoka和格点三角形 这个题目不是很难,不过要考虑周全,面积是1,那么底边的长度可以是1也可以是2, 注意底边1和2会有重复的, ...

  3. 2020牛客寒假算法基础集训营4-F树上博弈

    链接:https://ac.nowcoder.com/acm/contest/3005/F来源:牛客网 题目描述 现有一个 n 个点,n-1条边组成的树,其中 1 号点为根节点. 牛牛和牛妹在树上玩游 ...

  4. 2020牛客寒假算法基础集训营4-I 匹配星星【贪心】

    链接:https://ac.nowcoder.com/acm/contest/3005/I来源:牛客网 示例1 输入 复制 2 1 1 0 2 2 1 2 1 1 0 2 2 1 输出 复制 1 1 ...

  5. 牛客寒假算法基础集训营4 F Applese 的大奖

    链接:https://ac.nowcoder.com/acm/contest/330/H来源:牛客网 Applese 和它的小伙伴参加了一个促销的抽奖活动,活动的规则如下:有一个随机数生成器,能等概率 ...

  6. 牛客寒假算法基础集训营4 F Applese 的QQ群

    链接:https://ac.nowcoder.com/acm/contest/330/F来源:牛客网 Applese 有一个QQ群.在这个群中,大家互相请教问题.如 b 向 a 请教过问题,就把 a ...

  7. 2020牛客寒假算法基础集训营5 G街机争霸

    题目描述 哎,又是银首,要是你这个签到题少WA一发就金了 牛牛战队的队员打完比赛以后又到了日常甩锅的时间.他们心情悲伤,吃完晚饭以后,大家相约到一个街机厅去solo.牛牛和牛能进入了一个迷宫,这个迷宫 ...

  8. 2020牛客寒假算法基础集训营4 D:子段异或

    D : 子段异或 考察点 : 位运算,前缀和,异或的性质和应用 坑点 : 0 - L 的异或值是 0 的话也是一个区间 相同的值可能有多个,那么这时候区间就会有多个(x * (x + 1) / 2) ...

  9. 2020牛客寒假算法基础集训营6 I.导航系统 (最小生成树)

    https://ac.nowcoder.com/acm/contest/3007/I 题中给定的图必定是一棵树 容易发现,如果将输入的N(N-1)个距离看做N(N-1)条无向边的话,那么如果数据合法, ...

随机推荐

  1. 解决IIS程序池回收webapi定时程序造成的影响

    问题描述: webapi中有一个定时器线程,在iis程序池在1740分钟回收后,定时器中止 问题解决步骤: 1.设置程序池定期回收,设置每天定时回收 2.在windows自带的任务计划中,添加一条任务 ...

  2. JavaScript-装饰器模式

    装饰器模式 为对象添加新功能 不改变其原有的结构和功能 传统 UML 类图 javascript 中的装饰器 装饰类 @testDec clss Demo { } function testDec(t ...

  3. [PHP] 使用PHP在mongodb中进行嵌套查询

    作为文档数据库,数据库中存储的数据是类似json的结构,比如{“modelInfo”:{"status":1,audited:"1"}},想要查询status是 ...

  4. 极具性价比优势的工业控制以及物联网解决方案-米尔MYD-C8MMX开发板测评

    今天要进行测评的板子是来自米尔电子的MYD-C8MMX开发板.MYD-C8MMX开发板是米尔电子基于恩智浦,i.MX 8M Mini系列嵌入式应用处理器设计的开发套件,具有超强性能.工业级应用.10年 ...

  5. 获取Windows平台下 安装office 版本位数信息

    最近在处理客户端安装程序过程,有一个需求:需要检测Windows平台下安装office 版本信息以及获取使用的office是32 位还是64 位: 当检测出office 位数为64位时,提示当前off ...

  6. day 8 函数编程_byets

    定义 bytes类型是指一堆字节的集合,在python中以b开头的字符串都是bytes类型 b'\xe5\xb0\x8f\xe7\x8c\xbf\xe5\x9c\x88' #b开头的都代表是bytes ...

  7. opencv —— erode、dilate 腐蚀与膨胀

    腐蚀与膨胀是形态学滤波.其中,腐蚀是最小值滤波,膨胀是最大值滤波,即分别选取内核中的最小值与最大值赋值给锚点.若内核为 N×1 或 1×N 形状,可用于横纵方向直线检测. 膨胀:dilate 函数 v ...

  8. UVA-1588

    只用C来写 题目:https://vjudge.net/problem/UVA-1588 #include<stdio.h> #include<string.h> #defin ...

  9. D. Domino for Young

    基本思想是利用涂色的方法,用黑白两种颜色把方格全部涂色,相邻方格不同色. 方法1:基于二分图匹配的思想 一开始也想过二分图匹配,但数据量太大,就放弃了这种想法.其实根据增广路的定义.如果白色的方格的数 ...

  10. PP: Time series anomaly detection with variational autoencoders

    Problem: unsupervised anomaly detection Model: VAE-reEncoder VAE with two encoders and one decoder. ...