题意

\(T\) 组数据,每组数据给定一棵 \(n\) 个点的树和 \(m\) 条路径,求选出 \(k\) 条给定路径使得至少有两条交于一点的方案数,对 \(10^9+7\) 取模。

\(\texttt{Data Range:}1\leq T\leq 200,1\leq n\leq 3\times 10^5,2\leq m\leq 3\times 10^5,2\leq k\leq m\)。

题解

这种题都不能一次 AC,而且还是犯的弱智错误,我太菜了。

考虑这样一个结论:如果两条路径交于一些点,那么这些点中的某一个肯定是这两条路径中一条的两个端点的 LCA。

我们枚举这样一个端点,然后容斥。设 \(u_x\) 为这些路径中经过 \(x\) 的数量,\(v_x\) 为这些路径中两个端点的 LCA 为 \(x\) 的数量,那么答案为

\[\sum\limits_{i=1}^{n}\binom{u_i}{k}-\binom{u_i-v_i}{k}
\]

然后 \(v\) 是很容易维护的,\(u\) 树上差分一下就好了。

所以我们容易看出邪王真眼是最强的!!!

代码

#include<bits/stdc++.h>
using namespace std;
typedef int ll;
typedef long long int li;
const ll MAXN=3e5+51,MOD=1e9+7;
struct Edge{
ll to,prev;
};
Edge ed[MAXN<<1];
ll test,n,m,kk,tot,from,to,lca,res;
ll last[MAXN],u[MAXN],v[MAXN],depth[MAXN],anc[MAXN][20],fact[MAXN];
ll finv[MAXN],f[MAXN],diff[MAXN];
inline ll read()
{
register ll num=0,neg=1;
register char ch=getchar();
while(!isdigit(ch)&&ch!='-')
{
ch=getchar();
}
if(ch=='-')
{
neg=-1;
ch=getchar();
}
while(isdigit(ch))
{
num=(num<<3)+(num<<1)+(ch-'0');
ch=getchar();
}
return num*neg;
}
inline ll qpow(ll base,ll exponent)
{
ll res=1;
while(exponent)
{
if(exponent&1)
{
res=(li)res*base%MOD;
}
base=(li)base*base%MOD,exponent>>=1;
}
return res;
}
inline void setup(ll cnt)
{
fact[0]=fact[1]=finv[0]=1;
for(register int i=2;i<=cnt;i++)
{
fact[i]=(li)fact[i-1]*i%MOD;
}
finv[cnt]=qpow(fact[cnt],MOD-2);
for(register int i=cnt-1;i;i--)
{
finv[i]=(li)finv[i+1]*(i+1)%MOD;
}
}
inline ll binom(ll m,ll n)
{
return m<n?0:(li)fact[m]*finv[n]%MOD*finv[m-n]%MOD;
}
inline void addEdge(ll from,ll to)
{
ed[++tot].prev=last[from];
ed[tot].to=to;
last[from]=tot;
}
inline void dfs(ll node,ll fa)
{
depth[node]=depth[anc[node][0]=fa]+1;
for(register int i=last[node];i;i=ed[i].prev)
{
ed[i].to!=fa?dfs(ed[i].to,node):(void)1;
}
}
inline void LCASetup()
{
for(register int j=1;j<20;j++)
{
for(register int i=1;i<=n;i++)
{
anc[i][j]=anc[anc[i][j-1]][j-1];
}
}
}
inline ll LCA(ll x,ll y)
{
depth[x]<depth[y]?swap(x,y):(void)1;
for(register int i=19;i>=0;i--)
{
depth[anc[x][i]]>=depth[y]?x=anc[x][i]:1;
}
for(register int i=19;i>=0;i--)
{
anc[x][i]!=anc[y][i]?x=anc[x][i],y=anc[y][i]:1;
}
return x==y?x:anc[x][0];
}
inline void dfs2(ll node,ll fa)
{
ll to;
for(register int i=last[node];i;i=ed[i].prev)
{
(to=ed[i].to)!=fa?dfs2(to,node),diff[node]+=diff[to]:1;
}
}
inline void solve()
{
n=read(),m=read(),kk=read(),tot=0,memset(last,0,sizeof(last));
for(register int i=0;i<n-1;i++)
{
from=read(),to=read(),addEdge(from,to),addEdge(to,from);
}
dfs(1,0),LCASetup(),memset(f,0,sizeof(f)),memset(diff,0,sizeof(diff));
for(register int i=1;i<=m;i++)
{
u[i]=read(),v[i]=read(),f[lca=LCA(u[i],v[i])]++;
diff[u[i]]++,diff[v[i]]++,diff[lca]--,diff[anc[lca][0]]--;
}
dfs2(1,0),res=0;
for(register int i=1;i<=n;i++)
{
res=(res+(binom(diff[i],kk)-binom(diff[i]-f[i],kk)+MOD)%MOD)%MOD;
}
printf("%d\n",res);
}
int main()
{
test=read(),setup(300010);
for(register int i=0;i<test;i++)
{
solve();
}
}

Gym102012G Rikka with Intersections of Paths的更多相关文章

  1. 2018-2019 ACM-ICPC, Asia Xuzhou Regional Contest Solution

    A. Rikka with Minimum Spanning Trees 题意: 给出一个图,求最小生成树的个数和权值 思路: 因为数据随机,只有一个MST #include <bits/std ...

  2. 2018-2019 ACM-ICPC 徐州区域赛 部分题解

    题目链接:2018-2019 ACM-ICPC, Asia Xuzhou Regional Contest A. Rikka with Minimum Spanning Trees 题意: 给出一个随 ...

  3. POJ 3177 Redundant Paths & POJ 3352 Road Construction(双连通分量)

    Description In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numb ...

  4. hdu1625 Numbering Paths (floyd判环)

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission ...

  5. [LeetCode] Binary Tree Paths 二叉树路径

    Given a binary tree, return all root-to-leaf paths. For example, given the following binary tree: 1 ...

  6. [LeetCode] Unique Paths II 不同的路径之二

    Follow up for "Unique Paths": Now consider if some obstacles are added to the grids. How m ...

  7. [LeetCode] Unique Paths 不同的路径

    A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). The ...

  8. leetcode : Binary Tree Paths

    Given a binary tree, return all root-to-leaf paths. For example, given the following binary tree: 1 ...

  9. UVA 10564 Paths through the Hourglass[DP 打印]

    UVA - 10564 Paths through the Hourglass 题意: 要求从第一层走到最下面一层,只能往左下或右下走 问有多少条路径之和刚好等于S? 如果有的话,输出字典序最小的路径 ...

随机推荐

  1. fastjson 1.2.6以下版本 解析字符串末尾出现/x会陷入死循环 报oom异常

    记一次使用阿里fastjson遇到的问题 项目最好将fastjson版本升级到1.2.6或以上版本 1.2.6以下版本存在漏洞,测试如下代码直接报错 public class FastJsonTest ...

  2. spring注解(Component、依赖注入、生命周期、作用域)

    1.注解 注解就是一个类,使用@加上注解名称,开发中可以使用注解取代配置文件 2.@Component 取代<bean  class="">,@Component 取代 ...

  3. Centos-重定向方式打包、备份、还原、恢复工具-cpio

    cpio 通过重定向方式将文件进行打包.备份.还原.恢复工具,扩展名为 .cpio 相关选项 -o 将文件复制.打包成文件或将将文件输出到标准输出 -i  将打包文件或者将设备上的备份还原到系统中 - ...

  4. Harmony OS 开发避坑指南——DevEco Device Tool 安装配置

    Harmony OS 开发指南--DevEco Device Tool 安装配置 本文介绍如何在Windows主机上安装DevEco Device Tool工具. 坑点总结: 国内部分网络环境下,安装 ...

  5. Regression trees树回归 以及其他

    https://www.cnblogs.com/wuliytTaotao/p/10724118.html 选 weighted variance 最小的 但是weighted variance是怎么计 ...

  6. C#设计模式-适配器模式(Adapter Pattern)

    概念 把一个类的接口变换成客户端所期待的另一种接口,从而使原本接口不匹配而无法一起工作的两个类能够在一起工作.适配器模式有类的适配器模式和对象的适配器模式两种形式.前者类之间的耦合度比后者高,且要求程 ...

  7. 047 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 09 嵌套while循环应用

    047 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 09 嵌套while循环应用 本文知识点:嵌套while循环应用 什么是循环嵌套? 什么是循环嵌套? ...

  8. LiteOS-任务篇-源码分析-系统启动函数

    目录 前言 链接 参考 开启调度 LOS_Start 函数源码 osTickStart 函数源码 LOS_StartToRun 函数源码 前言 20201009 移植好内核后,开始实战内核. 源码分析 ...

  9. 十一长假我肝了这本超硬核PDF,现决定开源!!

    写在前面 在 [冰河技术] 微信公众号中的[互联网工程]专题,更新了不少文章,有些读者反馈说,在公众号中刷 历史文章不太方便,有时会忘记自己看到哪一篇了,当打开一篇文章时,似乎之前已经看过了,但就是不 ...

  10. es使用--新建、删除、增删改数据

    # 进入bin目录 cd /czz/elsearch/bin # 后台启动(不加-d参数则是前台启动,日志在控制台) # 后台启动日志如果不配置,在es目录的logs下面 ./elasticsearc ...