P3914 染色计数

题目描述

有一颗NN个节点的树,节点用1,2,\cdots,N1,2,⋯,N编号。你要给它染色,使得相邻节点的颜色不同。有MM种颜色,用1,2,\cdots,M1,2,⋯,M编号。每个节点可以染MM种颜色中的若干种,求不同染色方案的数量除以(10^9 + 7109+7)的余数。

输入输出格式

输入格式:

第1 行,2 个整数N,MN,M。

接下来NN行,第ii行表示节点ii可以染的颜色。第1个整数k_iki​,表示可以染的颜色数量。接下来k_iki​个整数,表示可以染的颜色编号。

最后N - 1N−1行,每行2个整数A_i,B_iAi​,Bi​,表示边(A_i,B_i)(Ai​,Bi​)。

输出格式:

1 个整数,表示所有的数。

输入输出样例

输入样例#1: 复制

  1. 2 2
  2. 1 1
  3. 2 1 2
  4. 1 2
输出样例#1: 复制

  1. 1

说明

• 对于30% 的数据,1 \le N \le 10; 1 \le M \le 41≤N≤10;1≤M≤4;

• 对于60% 的数据,1 \le N \le 200; 1 \le M \le 2001≤N≤200;1≤M≤200;

• 对于100% 的数据,1 \le N \le 5000; 1 \le M \le 50001≤N≤5000;1≤M≤5000。

dfs+组合数学 爆零、、(可能是我写的问题)

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<iostream>
  4. #include<algorithm>
  5. #define N 5100
  6. #define LL long long
  7. #define mod 1000000007
  8. using namespace std;
  9. long long ans;
  10. bool vis[N],vist[N],boo[N][N];
  11. int n,m,x,y,tot,k[N],head[N],a[N][N],same[N][N];
  12. int read()
  13. {
  14. ,f=; char ch=getchar();
  15. ;ch=getchar();}
  16. +ch-',ch=getchar();
  17. return x*f;
  18. }
  19. struct Edge
  20. {
  21. int to,next;
  22. }edge[N];
  23. int add(int x,int y)
  24. {
  25. tot++;
  26. edge[tot].to=y;
  27. edge[tot].next=head[x];
  28. head[x]=tot;
  29. }
  30. int dfs(int x)
  31. {
  32. for(int i=head[x];i;i=edge[i].next)
  33. {
  34. int t=edge[i].to;
  35. if(!vis[t])
  36. {
  37. vis[t]=true;
  38. if(!vist[t])
  39. {
  40. vist[t]=true;
  41. ans=(ans%mod+1ll*(k[x]-same[x][t])*k[t]%mod+(1ll*same[x][t]*(k[t]-)%mod))%mod;
  42. }
  43. dfs(t);
  44. vis[t]=false;
  45. }
  46. }
  47. }
  48. int main()
  49. {
  50. n=read(),m=read();
  51. ;i<=n;i++)
  52. {
  53. k[i]=read();
  54. ;j<=k[i];j++)
  55. a[i][j]=read(),boo[i][a[i][j]]=true;
  56. }
  57. ;i<n;i++)
  58. {
  59. x=read(),y=read();
  60. add(x,y),add(y,x);
  61. ;j<=k[y];j++)
  62. if(boo[x][a[y][j]])
  63. same[x][y]++,same[y][x]++;
  64. }
  65. vist[]=);
  66. printf("%lld",ans);
  67. ;
  68. }

0分代码

不会做了,粘个题解

令f[i][j]f[i][j]表示以ii为根的这棵子树在ii为颜色jj的时候的方案数,根据乘法原理可得f[i][j]=πf[k][c]f[i][j]=πf[k][c] 其中kk是ii的所有儿子,cc是所有与jj不同的颜色。

因此我们可以很容易相处一个O(n^3)O(n3)的是算法:枚举所有点,枚举它的颜色,枚举每一个儿子,枚举儿子的颜色,因为一个点只有一个父亲,所以枚举儿子的那一层加上枚举每一个点一共是O(n)O(n)的。

回过头来再看数据n<=5000n<=5000,m<=5000m<=5000,上述的算法似乎运行起来很吃力。那我们需要向一个办法去将复杂度变成O(n^2)O(n2),仔细思考后我们会发现,其实枚举儿子那一层是没有必要的,因为我只要颜色不相同的总数,与其O(m)O(m)地去求和,不如之前在枚举到它的时候就处理好所有的和,然后O(1)O(1)地去剪掉这个颜色,从而求出除去这个颜色外的方案数,达到O(n^2)O(n2)的复杂度。

这道题还是很不错的,这种思想在很多时候都能用得上。

  1. # include <algorithm>
  2. # include <iostream>
  3. # include <cstring>
  4. # include <cstdio>
  5. # include <vector>
  6. # include <cmath>
  7. # define R register
  8. # define mod
  9.  
  10. using namespace std;
  11.  
  12. ][],h[],tot[],sum[],x,y,d;
  13. ];
  14.  
  15. inline void in(R int &a){
  16. R , f=;
  17. ; c = getchar();}
  18. )+(x<<)+c-',c = getchar();
  19. a=x*f;
  20. }
  21.  
  22. inline void add(R int x,R int y){
  23. ed[++e] = (pp){y,h[x]};
  24. h[x] = e;
  25. }
  26.  
  27. inline void dfs(R int fa,R int x){//树形DP一般用DFS来实现
  28. for(R int i=h[x]; i; i=ed[i].pre)
  29. {
  30. R int p = ed[i].v;
  31. if(p == fa) continue;
  32. dfs(x,p);
  33. }
  34. ; j<=m; ++j)
  35. {
  36. if(!f[x][j]) continue;//没有这种颜色
  37. for(R int i=h[x]; i; i=ed[i].pre)
  38. {
  39. R int p = ed[i].v;
  40. if(p == fa) continue;
  41. f[x][j] = 1LL*f[x][j]*(tot[p]-f[p][j])%mod;
  42. }
  43. ) f[x][j] += mod;//上边(tot[p]-f[p][j])可能会变成负数,这里把它变回来。
  44. tot[x] = (1LL*tot[x]+1LL*f[x][j])%mod;
  45. }
  46. }
  47.  
  48. inline int yg(){
  49. in(n),in(m);
  50. ; i<=n; ++i)
  51. {
  52. in(sum[i]);
  53. ; j<=sum[i]; ++j) in(d),f[i][d]++;
  54. }
  55. ; i<n; ++i)
  56. {
  57. in(x),in(y);
  58. add(x,y),add(y,x);
  59. }
  60. add(,);//为了好写,新建一个原点连向1,这样就不用额外求tot[1]了
  61. dfs(,);
  62. cout << tot[];//tot[1]就是最终的答案
  63. }
  64.  
  65. int youngsc = yg();
  66. int main(){;}

洛谷——P3914 染色计数的更多相关文章

  1. 洛谷 P3914 染色计数

    P3914 染色计数 题目描述 有一颗NN个节点的树,节点用1,2,\cdots,N1,2,⋯,N编号.你要给它染色,使得相邻节点的颜色不同.有MM种颜色,用1,2,\cdots,M1,2,⋯,M编号 ...

  2. 洛谷P1144-最短路计数-最短路变形

    洛谷P1144-最短路计数 题目描述: 给出一个\(N\)个顶点\(M\)条边的无向无权图,顶点编号为\(1-N\).问从顶点\(1\)开始,到其他每个点的最短路有几条. 思路: \(Dijkstra ...

  3. 洛谷P2486 染色

    LCT的一种姿势. 题意:给定一棵树.每次把一条路径上的点染成一种颜色,求一条路径上有多少段颜色. 解: 首先可以很轻易的用树剖解决,只不过代码量让人望而却步... 有一种难以想象的LCT做法... ...

  4. 洛谷——P1176 路径计数2

    P1176 路径计数2 题目描述 一个N \times NN×N的网格,你一开始在(1,1)(1,1),即左上角.每次只能移动到下方相邻的格子或者右方相邻的格子,问到达(N,N)(N,N),即右下角有 ...

  5. 洛谷 P1176 路径计数2

    P1176 路径计数2 题目描述 一个N×N的网格,你一开始在(1, 1),即左上角.每次只能移动到下方相邻的格子或者右方相邻的格子,问到达(N, N),即右下角有多少种方法. 但是这个问题太简单了, ...

  6. 洛谷 P3130 [USACO15DEC]计数haybalesCounting Haybales

    P3130 [USACO15DEC]计数haybalesCounting Haybales 题目描述 Farmer John is trying to hire contractors to help ...

  7. 洛谷 P2807 三角形计数

    P2807 三角形计数 题目背景 三角形计数(triangle) 递推 题目描述 把大三角形的每条边n等分,将对应的等分点连接起来(连接线分别平行于三条边),这样一共会有多少三角形呢?编程来解决这个问 ...

  8. 洛谷P1608 路径计数

    题目简介 题目描述 给你一个N点M边的有向图,求第一个点到第n个点的最短路和最短路条数 题目分析 很明显直接Dijkstra求最短路,加一个最短路计数 如下: if(dis[y]>dis[x]+ ...

  9. P3914染色计数

    题目描述 有一颗\(N\)个节点的树,节点用\(1,2,\cdots,N\)编号.你要给它染色,使得相邻节点的颜色不同.有\(M\)种颜色,用\(1,2,\cdots,M\)编号.每个节点可以染\(M ...

随机推荐

  1. BZOJ 3262: 陌上花开 CDQ

    这个题大部分人用了离散然后水之,然而.....作为一只蒟蒻我并没有想到离散,而是直接拿两个区间一个对应n,一个对应k来搞,当然这两个区间是对应的,我把第一维排序,第二维CDQ,第三维树状数组,然而由于 ...

  2. JQuery选择器$()的工作原理浅析

    每次申明一个jQuery对象的时候,返回的是jQuery.prototype.init对象,很多人就会不明白,init明明是jQuery.fn的方法啊,实际上这里不是方法,而是init的构造函数,因为 ...

  3. HDU3488:Tour(KM算法)

    Tour Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Submis ...

  4. mybatis的注解功能

    一.mybatis 简单注解 关键注解词 : @Insert : 插入sql , 和xml insert sql语法完全一样 @Select : 查询sql, 和xml select sql语法完全一 ...

  5. MongoDB加索引

    1.登陆MongoDB, 命令行在MongoDB主目录下执行:mongo -port 27017 2.切换至需要添加索引的db 并授权 use MeetingBooking db.auth({&quo ...

  6. event对象和事件冒泡

    <!DOCTYPE HTML><html><head> <meta charset="utf-8"> <title>无标 ...

  7. java基础知识(二)-----多态和构造函数

    一:前言 最近由于面试了新浪公司,面试官问我的问题我都不知道,觉得自己好菜,所以最近决定再把java基础给搞一遍,真的觉得自己好菜.每天看一点,那个家伙说<java编程思想>最少要看三遍, ...

  8. mysql5.7.11安装遇到的问题

    首次安装mysql5.7.11绿色版,真是破费功夫,现记录安装中遇到的问题,只是解决了问题,而不清楚问题的由来. 问题一: 问题二: 问题三: 问题四: 我的my.ini配置文件: [mysql] # ...

  9. MDK stm32 仿真

    直接选择simulator,仿真时报错 *** error 65: access violation at 0x40021000 : no 'read' permission 修改系统配置,原配置如下 ...

  10. Linux中短横线(-)小记

    在Linux中短横线(-)可以表示输出流,具体用法如下. 搭配cat cat - 如果指定cat的文件为-,表示从标准输入读取(和直接使用cat,好像没什么区别) 搭配| echo 123 | cat ...