Kundu and Tree
2015-05-29 15:55
323 查看
Problem Statement
Russian
Chinese
Kundu是树的一个真正爱好者。树是一个包含N个点和N-1条边的连通图。今天,当他得到一棵树的时候,他给每条边涂上红色(‘r’)和黑色(’b’)之中的一种颜色。他有兴趣知道有多少个节点的三元组(a,b,c)满足在节点a到节点b、节点b到节点c和节点c到节点a的路径上,每条路径都至少有一条边是红色的。 请注意(a,b,c), (b,a,c)以及所有其他排列被认为是相同的三元组。 如果结果不小于 109 +
7, 输出结果对109 +
7取余的结果(%)。
输入格式
第一行包含一个整数N,测试数据的组数。 接下来的N-1行是边和颜色的表示,一组整数表示边,后面跟有边的颜色。颜色用一个小写英文字母来表示,是红色(‘r’)或者黑色(‘b’)。整数与整数、颜色字母之间由一个空格分隔。
输出格式
输出一个整数,表示三元组的数目。
*原始条件
1 ≤ N ≤
105
节点编号从1到 N。
输入样例
*输出样例
解释
给定的树如此
(2,3,4) 是一个满足条件的三元组,因为从2到3,3到4和2到4的每条路径都至少有一条红色的边。
(2,3,5), (1,3,4)和(1,3,5)是满足条件的其他三元组。
并查集+组合数学
Russian
Chinese
Kundu是树的一个真正爱好者。树是一个包含N个点和N-1条边的连通图。今天,当他得到一棵树的时候,他给每条边涂上红色(‘r’)和黑色(’b’)之中的一种颜色。他有兴趣知道有多少个节点的三元组(a,b,c)满足在节点a到节点b、节点b到节点c和节点c到节点a的路径上,每条路径都至少有一条边是红色的。 请注意(a,b,c), (b,a,c)以及所有其他排列被认为是相同的三元组。 如果结果不小于 109 +
7, 输出结果对109 +
7取余的结果(%)。
输入格式
第一行包含一个整数N,测试数据的组数。 接下来的N-1行是边和颜色的表示,一组整数表示边,后面跟有边的颜色。颜色用一个小写英文字母来表示,是红色(‘r’)或者黑色(‘b’)。整数与整数、颜色字母之间由一个空格分隔。
输出格式
输出一个整数,表示三元组的数目。
*原始条件
1 ≤ N ≤
105
节点编号从1到 N。
输入样例
[code]5 1 2 b 2 3 r 3 4 r 4 5 b
*输出样例
[code]4
解释
给定的树如此
(2,3,4) 是一个满足条件的三元组,因为从2到3,3到4和2到4的每条路径都至少有一条红色的边。
(2,3,5), (1,3,4)和(1,3,5)是满足条件的其他三元组。
并查集+组合数学
#include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <vector> #include <queue> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; const ll mod = 1000000000 + 7; const int maxn = 100010; int parent[maxn]; void init_set() { memset(parent, -1, sizeof(parent)); } int find_set(int x) { return parent[x] < 0 ? x : parent[x] = find_set(parent[x]); } void union_set(int x, int y) { int r1 = find_set(x); int r2 = find_set(y); if(r1 == r2) return ; if(parent[r1] < parent[r2]) { parent[r1] += parent[r2]; parent[r2] = r1; } else { parent[r2] += parent[r1]; parent[r1] = r2; } return ; } ll C(ll a, ll b) { ll res = 1LL; for(ll i = 0; i < b; ++i) { res *= (a - i); res /= (i + 1); } return res % mod; } int main() { //freopen("aa.in", "r", stdin); int n; int u, v; ll ans = 0; char col; vector<int> vec; init_set(); scanf("%d", &n); for(int i = 1; i < n; ++i) { scanf("%d %d %c", &u, &v, &col); if(col == 'b') { union_set(u, v); } } for(int i = 1; i <= n; ++i) { if(parent[i] < 0) { vec.push_back(-parent[i]); } } int len = vec.size(); for(int i = 0; i < len; ++i) { if(vec[i] > 1) { ans = (ans + C(vec[i], 2) * (n - vec[i])) % mod; } if(vec[i] > 2) { ans = (ans + C(vec[i], 3)) % mod; } } ans = ((C(n, 3) - ans) % mod + mod) % mod; printf("%lld\n", ans); return 0; }
相关文章推荐
- Single Number -- leetcode
- DOJO(一) Hello Dojo!!
- wince中的串口编程
- ios 常见问题
- ndk r9d for max下载地址
- java项目开发中MyEclipse新建工作空间后的配置详细步骤
- LA 3303 / POJ 2675 Songs (数学证明+排序)
- ajax调用.net webservice
- 【转】一张图学会python编程
- [Selenium] 如何使ChromeDriver 每次启动的端口不会随机变化
- CodeBlocks调试功能快捷教程
- jenkins + git+maven做持续集成测试版本控制(未完成版)
- 开源项目NumberProgressBar的简单使用
- easyui datagrid中动态改变某行的颜色
- 关于MemStore的刷新方式
- jsoup中文API
- Eclipse运行maven的jetty插件内存溢出解决
- 不受天气影响的文档管理
- Python中函数的参数定义和可变参数
- shell oracle(sqlplus spool)