链接: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. POJ 1753 Flip Game 暴力 深搜

    Flip Game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 59468   Accepted: 24750 Descr ...

  2. JavaScript之if流程控制演练,if写在区间内怎么解决

    什么是编程?通俗意见上来讲,就是把人的思维与步骤通过代码的形式书写展示出来,JavaScript的流程控制包含条件判断if,switch选择,循环for while:if(表达式 条件)=>真{ ...

  3. Javascript 基础学习(五)js 的运算符

    通过运算符可以对一个或多个值进行运算,并且一定有运算结果返回 算数运算符 ​ 算数运算符包括相加(+).相减(-).相乘(*).相除(/).取模(%).任何值与字符串相加都会转换为字符串,做的是字符串 ...

  4. Java架构师必看,超详细的架构师知识点分享!

    在Java程序员行业中,有不少Java开发人员的理想是成为一名优秀的Java架构师,Java架构师的主要任务不是从事具体的软件程序的编写,而是从事更高层次的开发构架工作.他必须对开发技术非常了解,并且 ...

  5. 【python基础语法】常用内置函数、关键字、方法和之间的区别(小结)

    ''' 关键字: False:bool数据类型 True:bool数据类型 None:表示数据的内容为空 and:逻辑运算符:与 or:逻辑运算符:或 not:逻辑运算符:非 in:身份运算符,判断变 ...

  6. elsearch搜索引擎 + painless脚本语言入门

    最近项目用到了elsearch,ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎. 自从版本6.0之后,其默认脚本语言变为 painless . ...

  7. LeetCode 面试题18. 删除链表的节点

    题目链接:https://leetcode-cn.com/problems/shan-chu-lian-biao-de-jie-dian-lcof/ 给定单向链表的头指针和一个要删除的节点的值,定义一 ...

  8. linux中 nodejs 安装 sqlite3 出现的问题

    错误代码类似:Error: Cannot find module '/root/QuickNote/node_modules/sqlite3/lib/binding/node-v57-linux-x6 ...

  9. ggEditor流程图增加网格背景

    参考官方文档: https://www.yuque.com/antv/g6/plugin.tool.grid react-ggEditor如何使用 import { Flow } from 'gg-e ...

  10. C# MVC Api无法获得参数

    在MVC中写API时,没有收到参数如何解决? 通过jQuery.POST测试成功.后来又通过F12发送,发现始终无法收到参数. 注:我的接口接收参数是一个类对象,没有写[FromBody]) [Htt ...