G.coloring tree BFS计数

题目:给你n(<=5000)个节点的一颗树 你有K(<=5000)种颜色 你可以给每一个节点染一种颜色

总共有Kn种染色方法 在一种染色方法中 定义colorness为每一对相同颜色节点距离中的最短距离

问colorness为D时 有多少种染色方案 结果%mod

解:我们先求出>=D的方案数再减去>=D+1的方案数就是==D的方案数

现在问题变为>=X的方案数 可以看成对于任意一个节点,所有和它距离小于d的节点,不能和它有相同的颜色

然后我们随便找个根节点开始bfs染色,怎么染色呢?
我们考虑根节点,它有k种颜色可以染,我们给根染了一种颜色之后,所有和根在距离<d的点,可以被染的颜色都会少一种,
然后我们bfs对所有的节点都这样做,然后我们最后把每个点可以染的颜色种类数乘起来,就是我们需要的答案了。
上述思路代码实现应该是很简单的,因为数据范围只有5000,我们可以对每个点都dfs一次,求出所有点之间的距离。然后计算的时候每次都把距离<d的所有点可选颜色都-1。
代码实现不是主要部分,重点是为什么按照bfs的顺序去做可以保证答案正确呢?
这里就要考虑一个问题了。假如我们有两种颜色,每个节点不能和距离<=1的点有相同的颜色,我们要怎么做呢?
比如我们有三个节点
1->2->3
如果我们不按照bfs顺序来染色
1有两种染色方案,3也有两种染色方案,这样一看,2就没有染色方案了,最后乘出来的答案就会为0。这是为什么呢?
我们发现1和3可以选取的颜色有重复,然后作用到2这个节点就会出问题。
那么  为什么bfs能保证答案正确呢?
我画了很久的图。。发现了一个性质。。
如果我们按照bfs的顺序来选择颜色计算方案数的话,已经选过颜色的和当前节点距离在d以内的节点,一定两两距离都在d以内
就是说,当前节点距离d以内的已经选择过颜色的节点在选择颜色种类的时候一定会互相考虑到彼此节点,如果我们用dfs,就保证不了这个性质了。
感谢牛客多校群的大佬帮我完成了这个证明
当前bfs到的节点 和其它(bfs走过的&&到当前节点距离<d)的点,两两之间距离<d的证明如下:
dis(u,v)=dis(u,x)+dis(v,x)-*dis(lca(u,v),x)
当前枚举点为x,u,v是任意点,lca是对于x为根
设u为深度比较低的那个点,
dis(u,x)-dis(lca(u,v),x)是大于等于dis(v,lca(u,v))的
然后代进去就能发现dis(u,v)<=dis(v,x)的
/*Huyyt*/
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-;
const int dir[][] = {{, }, {, }, {, -}, { -, }, {, }, {, -}, { -, -}, { -, }};
const int mod = 1e9 + , gakki = + + + + 1e9;
const int MAXN = 1e5 + , MAXM = 1e5 + , MAXQ = , INF = 1e9;
const ll LLINF = (1LL << );
int to[MAXM << ], nxt[MAXM << ], Head[MAXN], tot = ;
inline void addedge(int u, int v)
{
if (u == v)
{
return ;
}
to[++tot] = v;
nxt[tot] = Head[u];
Head[u] = tot;
}
template <typename T> inline void read(T&x)
{
char cu = getchar();
x = ;
bool fla = ;
while (!isdigit(cu))
{
if (cu == '-')
{
fla = ;
}
cu = getchar();
}
while (isdigit(cu))
{
x = x * + cu - '', cu = getchar();
}
if (fla)
{
x = -x;
}
}
ll n, k, d;
ll dis[][];
ll val[];
void dfs(int s, int now, int pre)
{
for (int v, i = Head[now]; i; i = nxt[i])
{
v = to[i];
if (v == pre)
{
continue;
}
dis[s][v] = dis[s][now] + ;
dfs(s, v, now);
}
}
ll get_ans(ll d)
{
queue<ll> q;
q.push();
for (int i = ; i <= n; i++)
{
val[i] = k;
}
ll ans = ;
while (!q.empty())
{
ll i = q.front();
q.pop();
ll res = ;
for (int j = ; j <= n; j++)
{
if (i != j)
{
val[j] -= dis[i][j] < d;
}
}
if(val[i]<=)
return ;
ans=ans*val[i]%mod;
for(int v,j=Head[i];j;j=nxt[j])
{
v=to[j];
if(dis[][i]+==dis[][v])
{
q.push(v);
}
}
}
return ans;
}
int main()
{
ios_base::sync_with_stdio();
cin.tie(); read(n), read(k), read(d);
int u, v;
for (int i = ; i < n; i++)
{
read(u), read(v);
addedge(u, v), addedge(v, u);
}
for (int i = ; i <= n; i++)
{
dfs(i, i, -);
}
ll anser = (get_ans(d) - get_ans(d + ) + mod) % mod;
printf("%lld\n", anser);
return ;
}

uestc summer training #9 牛客第三场 BFS计数的更多相关文章

  1. 牛客第三场多校 E Sort String

    链接:https://www.nowcoder.com/acm/contest/141/E来源:牛客网 Eddy likes to play with string which is a sequen ...

  2. 牛客第三场多校 H Diff-prime Pairs

    链接:https://www.nowcoder.com/acm/contest/141/H来源:牛客网 Eddy has solved lots of problem involving calcul ...

  3. uestc summer training #4 牛客第一场

    A dp[i][j][k]可以n3地做 但是正解是找把问题转化为一个两点不相交路径 最终答案为C(n+m, n)2-C(n+m, m-1)C(n+m,n-1) B 把题目的矩阵看成无向图的邻接矩阵 这 ...

  4. Shuffle Cards(牛客第三场+splay)

    题目: 题意:将1~n的数进行m次操作,每次操作将第pi位到pi+si-1位的数字移到第一位,求最后的排列. 思路:现在还没不会写splay,在知道这是splay模板题后找了一波别人的模板,虽然过了, ...

  5. PACM Team(牛客第三场多校赛+dp+卡内存+打印路径)

    题目链接(貌似未报名的不能进去):https://www.nowcoder.com/acm/contest/141/A 题目: 题意:背包题意,并打印路径. 思路:正常背包思路,不过五维的dp很容易爆 ...

  6. 牛客第三场 J LRU management

    起初看到这道题的时候,草草就放过去了,开了另一道题,结果开题不顺利,总是感觉差一点就可以做出来,以至于一直到最后都没能看这道题qaq 题意:类似于操作系统上讲的LRU算法,有两个操作,0操作代表访问其 ...

  7. 最长相同01数的子串(map搞搞)--牛客第三场 -- Crazy Binary String

    题意: 如题. 或者用我的数组分治也可以,就是有点愚蠢. //#include <bits/stdc++.h> #include <map> #include <iost ...

  8. 平面割线平分点(构造)--牛客第三场-- Magic Line

    题意: 给你n个点的坐标,让你给出两个点,这两个点的连线可以平分这些点. 思路: 先按y的大小排序,在按x的小排序,再搞一下就行了.如下图: #include <bits/stdc++.h> ...

  9. 牛客第五场多校 J plan 思维

    链接:https://www.nowcoder.com/acm/contest/143/J来源:牛客网 There are n students going to travel. And hotel ...

随机推荐

  1. CnPack开发包基础库

    unit CnCommon; {* |<PRE> ===================================================================== ...

  2. 【D3D12学习手记】The Swap Chain and Page Flipping

    为了避免动画中的闪烁,最好将整个动画帧绘制到称为后台缓冲区的屏幕外纹理(off-screen texture)中.一旦整个场景被绘制到给定动画帧的后缓冲区,它就作为一个完整的帧呈现给屏幕;以这种方式, ...

  3. Oracle:常用操作(定时作业,逻辑导入,数据泵导入)

    1.逻辑导入: /*第1步:创建临时表空间 **/ create temporary tablespace user_temp1 tempfile 'D:\app\Administrator\orad ...

  4. jvm的学习笔记:二、类的初始化,代码实战(3)

    首次主动此用导致类的初始化 MyParent4 myParent4 = new MyParent4(); MyParent4 myParent5 = new MyParent4(); 输出: MyPa ...

  5. 【VS开发】内存泄漏相关问题

    之所以撰写这篇文章是因为前段时间花费了很大的精力在已经成熟的代码上再去处理memory leak问题.写此的目的是希望我们应该养成良好的编码习惯,尽可能的避免这样的问题,因为当你对着一大片的代码再去处 ...

  6. PHP Excel导入

    public function importFile() { $file = request()->file('file'); $params = $this->request->p ...

  7. python random 的用法

    python random的里面的方法其实是Random实例化的对象. 里面几个常用的几个方import random print( random.randint(1,10) ) # 产生 1 到 1 ...

  8. 在Ubuntu上安装Hive

    1.下载hive2.3.5 解压缩并改名为hive目录,放到/usr/local下(注意权限) sudo mv apache-hive-2.3.5-bin /usr/local/hive 2.修改目录 ...

  9. Maven简单项目及命令使用

    项目结构如下 HelloWorld.java package pak1; public class HelloWorld { public String sayHello(){ return &quo ...

  10. 喝奶茶最大值(不能喝自己班级的)2019 Multi-University Training Contest 8--hdu杭电第8场(Roundgod and Milk Tea)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6667 题意: 有 n个班级,每个班级有a个人.b个奶茶,每个班的人不能喝自己的奶茶,只能喝别人班的奶茶 ...