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

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

题目描述

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

 
 
 

输入描述:

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

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

输出描述:

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

输入

复制

3
WBW
1 2
2 3

输出

复制

3

说明

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

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

  

 #include <bits/stdc++.h>
#define dbg(x) cout << #x << "=" << x << endl using namespace std;
typedef long long LL;
const int maxn = 1e6 + ; int n;
LL ans;
int fa[maxn];
int a[maxn];
int head[maxn];
char c[maxn];
int cnt = ;
LL sz[maxn];
LL num[maxn];
int _count = ; //vector <int> g[maxn]; struct Edge {
int to,nxt;
}edge[maxn]; void BuildGraph(int u, int v) {
edge[cnt].to = v;
edge[cnt].nxt = head[u];
head[u] = cnt++; edge[cnt].to = u;
edge[cnt].nxt = head[v];
head[v] = cnt++;
} void init()
{
memset(head, -, sizeof(head));
for(int i = ; i <= n; i++) {
fa[i] = i;
sz[i] = ;
}
} namespace _buff {
const size_t BUFF = << ;
char ibuf[BUFF], *ib = ibuf, *ie = ibuf;
char getc() {
if (ib == ie) {
ib = ibuf;
ie = ibuf + fread(ibuf, , BUFF, stdin);
}
return ib == ie ? - : *ib++;
}
} int read() {
using namespace _buff;
int ret = ;
bool pos = true;
char c = getc();
for (; (c < '' || c > '') && c != '-'; c = getc()) {
assert(~c);
}
if (c == '-') {
pos = false;
c = getc();
}
for (; c >= '' && c <= ''; c = getc()) {
ret = (ret << ) + (ret << ) + (c ^ );
}
return pos ? ret : -ret;
} int fid(int x)
{
int r = x;
while(fa[r] != r) {
r = fa[r];
}
int i,j;///路径压缩
i = x;
while(fa[i] != r) {
j = fa[i];
fa[i] = r;
i = j;
}
return r;
} void join(int r1,int r2)///合并
{
int fidroot1 = fid(r1), fidroot2 = fid(r2);
int root = min(fidroot1, fidroot2);
sz[root] = sz[fidroot1] + sz[fidroot2];
if(fidroot1 != fidroot2) {
fa[fidroot2] = root;
fa[fidroot1] = root;
}
} LL _find(int x) {
//dbg(x);
LL sum = ;
for(int i = head[x]; ~i; i = edge[i].nxt) {
int v = edge[i].to;
if(a[v]) {
//num[v] = 0;
continue;
}
int r1 = fid(x), r2 = fid(v);
sum += sz[r2];
num[++_count] = sz[r2];
}
return sum;
} int main()
{
scanf("%d\n",&n);
init();
ans = ;
scanf("%s",c);
for(int i = ; i < n; ++i) {
if(c[i] == 'W') {
a[i+] = ;
}
else {
a[i+] = ;
}
}
for(int i = ; i < n; ++i) {
int x, y;
scanf("%d %d",&x, &y);
BuildGraph(x,y);
if(!a[x] && !a[y]) {
join(x,y);
}
}
for(int i = ; i <= n; ++i) {
if(a[i] == ) continue;
_count = ;
memset(num, , sizeof(num));
ans += _find(i);
for(int j = ; j <= _count; ++j) {
for(int k = j+; k <= _count; ++k) {
ans += num[j] * num[k];
}
}
} printf("%lld\n",ans);
}
 

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. sublime text3 安装详解+前端插件

    1,下载sublime 3,地址:http://www.sublimetext.com/ 2,注册码:(在网上找的,感谢前辈)打开sublime3, help----add license---复制下 ...

  2. 异常 lock buffer failed for format 0x23

    02-11 21:21:45.669625 14804 14815 W Monkey : // java.lang.RuntimeException: lock buffer failed for f ...

  3. 移动app

    什么是移动App开发[重点] 苹果上的软件是如何开发出来的:使用IOS平台的开发工具和开发语言进行设计开发的!苹果上的开发语言:OC.Swift 安卓平台上的软件又是如何开发出来的:使用Java这么语 ...

  4. opencv —— boundingRect、minAreaRect 寻找包裹轮廓的最小正矩形、最小斜矩形

    寻找包裹轮廓的最小正矩形:boundingRect 函数 返回矩阵应满足:① 轮廓上的点均在矩阵空间内.② 矩阵是正矩阵(矩形的边界与图像边界平行). Rect boundingRect(InputA ...

  5. Html介绍,认识head标签

    <head></head>标签位于html文档的头部,主要是用来描述文档的各种属性和信息,包括文档的标题等,当然文档头部包含的数据都不会真正作为内容展示给访客的. 如下的一些标 ...

  6. mysql必知必会--MySQL简介

    什么是MySQL MySQL已经存在很久了,它在世界范围内得到了广泛的安装和使用. 为什么有那么多的公司和开发人员使用MySQL?以下列出其原因. 成本--MySQL是开放源代码的,一般可以免费使用( ...

  7. linux | 一次网卡故障处理

    问题 在centos7系统中,设置ifcfg-eth*文件时,总会纠结NAME和DEVICE到底写哪个或哪个真实生效.这里实例演示下 这是网卡ifcfg-eth4配置文件.没写DEVICE,用的NAM ...

  8. PHP0019:PHP 图像验证码 、图像水印效果 、 生成缩约图

  9. 【剑指Offer】61、把二叉树打印成多行

    题目描述 从上到下按层打印二叉树,同一层结点从左至右输出.每一层输出一行. 题解一:BFS public static ArrayList<ArrayList<Integer>> ...

  10. Linux进程间通信-管道深入理解(转)

    原文地址:https://www.linuxidc.com/Linux/2018-04/151680.htm Linux进程通信系列文章将详细介绍各种通信方式的机制和区别 1.进程间通信 每个进程各自 ...