多彩的树 -----题解(状压dp + 容斥原理)

目录

多彩的树

题目描述 

输入描述:

输出描述:

输入

输出

思路解析:

代码实现:


多彩的树

时间限制:C/C++ 5秒,其他语言10秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述 

有一棵树包含 N 个节点,节点编号从 1 到 N。节点总共有 K 种颜色,颜色编号从 1 到 K。第 i 个节点的颜色为 Ai。
Fi 表示恰好包含 i 种颜色的路径数量。请计算:

输入描述:

第一行输入两个正整数 N 和 K,N 表示节点个数,K 表示颜色种类数量。
第二行输入 N 个正整数,A1, A2, A3, ... ..., AN,Ai 表示第 i 个节点的颜色。

接下来 N - 1 行,第 i 行输入两个正整数 Ui 和 Vi,表示节点 Ui 和节点 Vi 之间存在一条无向边,数据保证这 N-1 条边连通了 N 个节点。

1 ≤ N ≤ 50000.
1 ≤ K ≤ 10.
1 ≤ Ai ≤ K.

输出描述:

输出一个整数表示答案。

示例1

输入

复制

5 3
1 2 1 2 3
4 2
1 3
2 1
2 5

输出

复制

4600065

思路解析:

状压dp + 容斥原理

dp[i] 表示在状态i下·的路径树, 状态i用二进制表示,i==10010,表示使用了颜色2和5,因为这里考虑已经使用了那些颜色比考虑现在的使用的颜色数量更任意统计,并且状态更加明确方便状态转移。

cnt 表示在状态10010下,在某个位置有多少个颜色2和5的节点相邻。cnt + (cnt) * (cnt - 1) / 2则表示当前状态下可能的路径方案总数。

dp[i] = (dp[i] + cnt + (cnt) * (cnt - 1) / 2) % mod;

因为可能有可能是 2 2 2 2 5 5 5.这样简单的cnt + (cnt) * (cnt - 1) / 2计算可能会导致计算有误,所以要排除非法答案。即状态为 00010和状态10000的情况。

if ((j & i) == j){
// System.out.println(i + " " + j);
dp[i] = (dp[i] - dp[j] + mod) % mod;
}

代码实现:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.Arrays;
import java.util.Scanner;
import java.util.Vector;

/**
 * @ProjectName: study3
 * @FileName: Ex35
 * @author:HWJ
 * @Data: 2023/11/10 11:45
 */
public class Ex35 {
    static int mod = 1000000007;
    static long[] dp;
    static long cnt;
    static Vector<Vector<Integer>> g;
    static int[] vis;
    static int[] col;

    public static void main(String[] args) throws IOException {
        Scanner input = new Scanner(System.in);
        StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
        in.nextToken();
        int n = (int) in.nval;
        in.nextToken();
        int m = (int) in.nval;
        int[] pow = new int[m + 1];
        for (int i = 0; i < m; i++) {
            pow[i + 1] = (int) quick(i + 1);
        }
        dp = new long[1 << m]; // 用颜色做状态转移。
        vis = new int[n + 1];
        g = new Vector<>();
        col = new int[n + 1];
        for (int i = 0; i < n; i++) {
            in.nextToken();
            col[i + 1] = (int) in.nval;
        }
        for (int i = 0; i < n + 1; i++) {
            g.add(new Vector<>());
        }
        for (int i = 0; i < n - 1; i++) {
            in.nextToken();
            int x = (int) in.nval;
            in.nextToken();
            int y = (int) in.nval;
            g.get(x).add(y);
            g.get(y).add(x);
        }
        for (int i = 1; i < 1 << m; i++) {
            Arrays.fill(vis, 0);
            for (int j = 1; j <= n; j++) {
                cnt = 0;
                if ((i & (1 << (col[j] - 1))) == 0 || vis[j] == 1) continue;
                dfs(j, 0, i);
                dp[i] = (dp[i] + cnt + (cnt) * (cnt - 1) / 2) % mod;
//                System.out.println(i + " " + (j - 1) + " " + cnt);
            }
            for (int j = i - 1; j > 0; j--) {
                if ((j & i) == j){
//                    System.out.println(i + " " + j);
                    dp[i] = (dp[i] - dp[j] + mod) % mod;
                }

            }
        }
        long ans = 0;
        for (int i = 1; i <1 << m; i++) {
            int t = 0;
            int k = i;
            System.out.println(dp[i]);
            while (k > 0){
                if ((k & 1) != 0) t++;
                k >>= 1;
            }
            ans = (ans + (long) pow[t] * dp[i]) % mod;
        }
        System.out.println(ans);
    }

    public static void dfs(int x, int fa, int st){
        cnt++;
        vis[x] = 1;
        for (int i = 0; i < g.get(x).size(); i++) {
            int y = g.get(x).get(i);
            if (y == fa || (st & (1 << (col[y] - 1))) == 0 || vis[y] == 1) continue;
            dfs(y, x, st);
        }
    }

    public static long quick(int p) {
        long ans = 1;
        long x = 131;
        for (; p > 0; p >>= 1, x = (x * x) % mod) {
            if ((p & 1) == 1) ans = (ans * x) % mod;
        }
        return ans;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/128623.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【算法练习Day42】买卖股票的最佳时机 III买卖股票的最佳时机 IV

​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 买卖股票的最佳时机 III买卖…

二十四、W5100S/W5500+RP2040树莓派Pico<PHY的状态模式控制>

文章目录 1. 前言2. 相关简介2.1 简述2.2 原理2.3 优点&应用 3. WIZnet以太网芯片4. PHY模式配置测试4.1 程序流程图4.2 测试准备4.3 连接方式4.4 相关代码4.5 测试现象 5. 注意事项6. 相关链接 1. 前言 W5100S/W5500不仅支持自动PHY自动协商&#xff0c;而且支持用户自定义…

Java中的反射机制

获取字节码文件对象的三种方式 1&#xff0c;&#xff08;常用&#xff09;源代码阶段&#xff0c;Class.forName("全类名") 2&#xff0c;&#xff08;传参&#xff09;加载阶段 类名.class 3&#xff0c;&#xff08;前提有对象&#xff09;运行阶段 对象.getClas…

Mac使用brew搭建kafka集群

1. 第一步&#xff1a;单机搭建 单机搭建&#xff1a; 安装完后&#xff0c;默认自动安装对应版本zookeeper brew install kafka2.第二步&#xff1a;修改配置文件: 配置3个Kafka 第一个&#xff08;使用默认配置&#xff09; vi /opt/homebrew/etc/kafka/server.propertie…

相机标定:理论与实践

先讨论相机模型&#xff0c;说明投影关系的描述&#xff0c;介绍相机的内外参&#xff0c;最后完成标定。 一、内参含义 把需要标定的相机参数叫做内参&#xff08;intrinsics matrix&#xff09;&#xff0c;它决定了物体的实际位置Q在成像平面上的投影位置q&#xff0c;如下…

Django 缓存:提升Web应用性能详解

在构建动态Web应用时&#xff0c;性能往往是重要的关注点。Django, 作为一个高级Python Web框架&#xff0c;提供了一套全面的缓存系统帮助开发者提升网站性能&#xff0c;降低服务器负载&#xff0c;并改善用户体验。本文将深入讨论Django缓存机制&#xff0c;并通过示例展示如…

windows安装linux双系统启动盘的制作与恢复

下载镜像 Index of /ubuntu-releases/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 制作启动盘 准备一个U盘&#xff0c;注意备份&#xff0c;启动盘的制作过程中是将ISO烧录到U盘中&#xff0c;会将U盘中的原内容覆盖掉在网上下载Win32DiskImager软件包烧录ISO…

详解Java中的重写和重载 | 动态绑定和静态绑定

目录 一.重载 二.重写 三.重载和重写的区别 一.重载 重载(overload)&#xff0c;Java中为了提高编程效率&#xff0c;允许我们使用方法重载&#xff0c;具体体现在&#xff0c;对于多个方法&#xff0c;他们的方法名相同&#xff0c;但参数列表不同&#xff0c;我们则将这种…

不想努力了,有没有不用努力就能考上硕士的方法

今年&#xff0c;硕士研究生考试报考人数再次刷新了纪录&#xff0c;高达474万人次。 这些年考研一直在扩招&#xff0c;但是录取率却越来越低&#xff0c;内卷血腥程度可想而知&#xff01; 2020年研究生报考人数341万&#xff0c;录取人数99.05万&#xff0c;录取率29.05%。…

Maven-依赖管理机制

一、背景和起源 依赖管理是Maven的一个核心功能。管理单个模块项目的依赖相对比较容易&#xff0c;但是如果是多模块项目或者有几百个模块的项目就是一个巨大的挑战。 如果手动构建项目&#xff0c;那么就先需要梳理各个模块pom中定义的依赖和版本&#xff0c;然后进行下载到本…

【MySQL】表的增删改查(强化)

作者主页&#xff1a;paper jie_博客 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 本文录入于《MySQL》专栏&#xff0c;本专栏是针对于大学生&#xff0c;编程小白精心打造的。笔者用重金(时间和精力)打造&a…

物奇平台耳机宕机恢复功能实现

是否需要申请加入数字音频系统研究开发交流答疑群(课题组)&#xff1f;可加我微信hezkz17, 本群提供音频技术答疑服务&#xff0c;群赠送语音信号处理降噪算法&#xff0c;蓝牙音频&#xff0c;DSP音频项目核心开发资料, 物奇平台耳机宕机恢复功能实现 一 需求与场景 1 使…

TortoiseSVN 状态图标不显示的两种解决办法

文章目录 TortoiseSVN 方式解决注册表方式解决 TortoiseSVN 方式解决 在桌面或者资源管理器中鼠标右键打开 TortoiseSVN 设置选择 Icon Overlays (图标覆盖)Status cache&#xff08;状态缓存&#xff09; 选择 ‘Shell’ 选择 Icon Overlays&#xff08;图标覆盖&#xff09;…

基于AI智能分析网关的智慧视频监控系统一站式解决方案

1、功能概述 TSINGEE智能分析网关EasyCVR智慧视频监控系统基于云-边-端一体化协同架构&#xff0c;可兼容多协议、多类型的设备接入&#xff0c;实现视频数据采集、海量视频汇聚与处理、按需调阅、全网分发、 告警消息推送、数据级联共享、AI智能分析接入等视频能力服务&#…

我敢打赌,这个架构你一定知道!

大家好&#xff0c;我是鱼皮。开发后端项目时&#xff0c;我们最常见的一种架构模式就是 分层架构 。 所谓的分层架构&#xff0c;就是把系统自上而下分为多个不同的层&#xff0c;每一层都有特定的功能和职责&#xff0c;且只和自己的直接上层与直接下层 “打交道”。 分层架…

MySQL 数据库表格创建、数据插入及获取插入的 ID:Python 教程

创建表格 要在MySQL中创建表格&#xff0c;请使用"CREATE TABLE"语句。 确保在创建连接时定义了数据库的名称。 示例创建一个名为 “customers” 的表格&#xff1a; import mysql.connectormydb mysql.connector.connect(host"localhost",user"…

LDR6023AQ-PDHUB最简外围成本低搂到底就是干

USB-C PD协议里&#xff0c;SRC和SNK双方之间通过CC通信来协商请求确定充电功率及数据传输速率。当个设备需要充电时&#xff0c;它会发送消息去给适配器请求充电&#xff0c;此时充电器会回应设备的请求&#xff0c;并告知其可提供的档位功率&#xff0c;设备端会根据适配器端…

Java集合面试题

常见的java集合&#xff1f; 主要分为三类&#xff0c;List Map Set 列表 映射 集 集合相关的接口都在 java.util中 java集合的主要关系 List 特性&#xff1a; 存储的元素有序&#xff0c;可重复 Set 特性&#xff1a;存储的元素无序&#xff0c;不可重复 Map 特性…

【Proteus仿真】【51单片机】汽车尾灯控制设计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真51单片机控制器&#xff0c;使用按键、LED模块等。 主要功能&#xff1a; 系统运行后&#xff0c;系统运行后&#xff0c;系统开始运行&#xff0c;K1键控制左转向灯&#xff1b;…