博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
*[hackerrank]Kundu and Tree
阅读量:4884 次
发布时间:2019-06-11

本文共 1467 字,大约阅读时间需要 4 分钟。

此题是有一棵树,树中的边有红有黑。求节点(a,b,c)的组合个数,使得ab,bc,ac都至少经过一条红边。

思路是:只有红边有意义,那么黑边连接的点都可以归为等价类(并查集),之后就是组合问题。记X1+X2+X3+...+Xn为P1,二次方的和为P2,三次方的和为P3。那么结果为(P1^3-3*P2*P1-2*P3)/6。6是三个不相同元素的排列情况,P1^3是三个元素所有取的排列次数,中间是两个在一类的情况,*3表示有三种排列情况,最后是如果三个元素在一类,那么会在第二种情况中计算两遍。

还有个更简单的算法就是C(n,3),减所有C(x,3),再减C(x,2)*(n-x)表示三个点在一起和两个点在一起的。

#include 
#include
#include
using namespace std; #define MAX_N 100010const int M = 1000000007;int father[MAX_N]; // disjoint setint num[MAX_N]; // number of elements in disjoint set int find(int i){ if (father[i] == i) return i; return father[i] = find(father[i]);} void merge(int i, int j){ int x = find(i); int y = find(j); if (x == y) return; num[x] += num[y]; father[y] = x;} int main(){ int n; cin >> n; for (int i = 0; i <= n; i++) { father[i] = i; num[i] = 1; } for (int i = 0; i < (n-1); i++) { int a, b; cin >> a >> b; char c; cin >> c; if (c == 'b') { merge(a, b); } } long long p1 = 0; long long p2 = 0; long long p3 = 0; for (int i = 1; i <= n; i++) { if (father[i] == i) { int x = num[i]; p1 += x; p2 += x * x; p3 += x * x * x; } } long long result = (p1 * p1 * p1 - 3 * p2 * p1 + 2 * p3)/6; cout << result % M << endl;}

  

转载于:https://www.cnblogs.com/lautsie/p/3798165.html

你可能感兴趣的文章
计算机网络●通信协议
查看>>
在EditPlus里配置编译和运行java代码的方法
查看>>
gson所需jar包
查看>>
最干净的pyinstaller打包成exe应用程序方法
查看>>
Python中的数据类型
查看>>
讲给普通人听的分布式数据存储【转载】
查看>>
关于最短路
查看>>
Hbase记录-zookeeper部署
查看>>
Python pexpect出现错误‘module have no attribute "spawn" 解决办法
查看>>
vs2008 C# 怎么调试C++ dll[转]
查看>>
PHP的魔术方法
查看>>
警惕麦咖啡的"缓冲区溢出保护"引起的ASP.NET 中 System.OutOfMemoryException 的错误...
查看>>
optimizer_dynamic_sampling
查看>>
HTML(WEB)开发day05
查看>>
序列合并求前K小项 POJ2442
查看>>
unity点选构建Mesh并保存OBJ
查看>>
python kmeans实战 - 单机一层聚类(小玩具哦),下次再弄个分布式多次聚类
查看>>
Java主要有那几种文件类型?各自的作用是什么?
查看>>
我的第一个python web开发框架(29)——定制ORM(五)
查看>>
2017.11.18 手把手教你学51单片机-点亮LED
查看>>