一、题目

点此看题

二、解法

这道题很离谱啊,看上去是求一个最大值,其实是把生成树权值为 \(i\) 的个数都给算出来,因为权值很小。

既然是生成树可以考虑矩阵树定理,我们考虑他是求这样一个式子:

\[\sum\prod e_{w_i}
\]

对于这个乘法的理解是很灵活的,只要他能满足直接点值相乘就可以了,比如把边权换成一次多项式来做加法(就是 \(2020\) 年的联合省选题),而这道题是 \(\tt FWT\) 后做矩阵树定理,因为它满足点值相乘。

具体说来,也就是先求出只考虑边权为 \(v\) 的边的矩阵 \(mp[i][j][v]\) ,然后对每个 \(mp[i][j]\) 做 \(\tt FWT\) ,这里的 \(\tt FWT\) 要魔改一下,因为是每一位是独立的,所以每一位做一种 \(\tt FWT\) 是可以的(比如这一位是或运算就做或 \(\tt FWT\))

现在就满足点值相乘了,我们求出每个边权的行列式 \(c[v]\) ,然后对 \(c\) 做同样的 \(\tt IFWT\) ,就得到了每个边权的方案数了。注意我们要一直让所有权值为正才行。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int MOD = 1e9+7;
const int N = 75;
const int M = 4100;
#define int long long
int read()
{
int x=0,f=1;char c;
while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
int n,m,w,lim,inv,a[N][N][M],r[N][N],c[M];char s[M];
int qkpow(int a,int b)
{
int r=1;
while(b>0)
{
if(b&1) r=r*a%MOD;
a=a*a%MOD;
b>>=1;
}
return r;
}
void fwt(int *a,int n,int op)
{
for(int i=1,b=0;i<n;i<<=1,b++)
{
int p=i<<1;
if(s[b]=='|')
{
for(int j=0;j<n;j+=p)
for(int k=0;k<i;k++)
{
if(op==1) a[i+j+k]=(a[i+j+k]+a[j+k])%MOD;
else a[i+j+k]=(a[i+j+k]-a[j+k]+MOD)%MOD;
}
}
if(s[b]=='&')
{
for(int j=0;j<n;j+=p)
for(int k=0;k<i;k++)
{
if(op==1) a[j+k]=(a[i+j+k]+a[j+k])%MOD;
else a[j+k]=(a[j+k]-a[i+j+k]+MOD)%MOD;
}
}
if(s[b]=='^')
{
for(int j=0;j<n;j+=p)
for(int k=0;k<i;k++)
{
int x=a[j+k],y=a[i+j+k];
a[j+k]=(x+y)%MOD;
a[i+j+k]=(x-y+MOD)%MOD;
if(op==-1)
{
a[j+k]=a[j+k]*inv%MOD;
a[i+j+k]=a[i+j+k]*inv%MOD;
}
}
}
}
}
int zy()
{
int ans=1;
for(int i=1;i<n;i++)
{
for(int j=i+1;j<n;j++)
if(!r[i][i] && r[j][i])
{
ans=MOD-ans;//手误了
swap(r[i],r[j]);
break;
}
if(!r[i][i]) return 0;
int iv=qkpow(r[i][i],MOD-2);
for(int j=i+1;j<n;j++)
{
int t=r[j][i]*iv%MOD;
for(int k=i;k<n;k++)
r[j][k]=(r[j][k]-t*r[i][k]%MOD+MOD)%MOD;
}
ans=ans*r[i][i]%MOD;
}
return ans;
}
signed main()
{
n=read();m=read();inv=(MOD+1)/2;
scanf("%s",s);w=strlen(s);lim=1<<w;
for(int i=1;i<=m;i++)
{
int u=read(),v=read(),c=read();
a[u][v][c]=(a[u][v][c]+MOD-1)%MOD;
a[v][u][c]=(a[v][u][c]+MOD-1)%MOD;
a[u][u][c]++;a[v][v][c]++;
}
for(int i=1;i<n;i++)
for(int j=1;j<n;j++)
fwt(a[i][j],lim,1);
for(int i=0;i<lim;i++)
{
memset(r,0,sizeof r);
for(int j=1;j<n;j++)
for(int k=1;k<n;k++)
r[j][k]=a[j][k][i];
c[i]=zy();
}
fwt(c,lim,-1);
for(int i=lim-1;i>=0;i--)
if(c[i]>0)
{
printf("%lld\n",i);
return 0;
}
puts("-1");
}

[THUPC2019] 找树的更多相关文章

  1. 洛谷 P5406 - [THUPC2019]找树(FWT+矩阵树定理)

    题面传送门 首先看到这道题你必须要有一个很清楚的认识:这题新定义的 \(\oplus\) 符号非常奇怪,也没有什么性质而言,因此无法通过解决最优化问题的思路来解决这个问题,只好按照计数题的思路来解决, ...

  2. poj 1655 Balancing Act(找树的重心)

    Balancing Act POJ - 1655 题意:给定一棵树,求树的重心的编号以及重心删除后得到的最大子树的节点个数size,如果size相同就选取编号最小的. /* 找树的重心可以用树形dp或 ...

  3. Leetcode之深度优先搜索(DFS)专题-513. 找树左下角的值(Find Bottom Left Tree Value)

    Leetcode之深度优先搜索(DFS)专题-513. 找树左下角的值(Find Bottom Left Tree Value) 深度优先搜索的解题详细介绍,点击 给定一个二叉树,在树的最后一行找到最 ...

  4. LeetCode 513. 找树左下角的值(Find Bottom Left Tree Value)

    513. 找树左下角的值 513. Find Bottom Left Tree Value 题目描述 给定一个二叉树,在树的最后一行找到最左边的值. LeetCode513. Find Bottom ...

  5. 【题解】#6622. 「THUPC 2019」找树 / findtree(Matrix Tree+FWT)

    [题解]#6622. 「THUPC 2019」找树 / findtree(Matrix Tree+FWT) 之前做这道题不理解,有一点走火入魔了,甚至想要一本近世代数来看,然后通过人类智慧思考后发现, ...

  6. Java实现 LeetCode 513 找树左下角的值

    513. 找树左下角的值 给定一个二叉树,在树的最后一行找到最左边的值. 示例 1: 输入: 2 / \ 1 3 输出: 1 示例 2: 输入: 1 / \ 2 3 / / \ 4 5 6 / 7 输 ...

  7. 1090 Highest Price in Supply Chain (25 分)(模拟建树,找树的深度)牛客网过,pat没过

    A supply chain is a network of retailers(零售商), distributors(经销商), and suppliers(供应商)-- everyone invo ...

  8. Codeforces Beta Round #87 (Div. 2 Only)-Party(DFS找树的深度)

    A company has n employees numbered from 1 to n. Each employee either has no immediate manager or exa ...

  9. poj 1655 找树的重心

    树形DP 求树的重心,即选择一个结点删去,使得分出的 若干棵树的结点数 的最大值最小 #include<map> #include<set> #include<cmath ...

随机推荐

  1. K8S(09)交付实战-通过流水线构建dubbo服务

    k8s交付实战-流水线构建dubbo服务 目录 k8s交付实战-流水线构建dubbo服务 1 jenkins流水线准备工作 1.1 参数构建要点 1.2 创建流水线 1.2.1 创建流水线 1.2.2 ...

  2. Python 是什么语言

    Python 是 解释型语言,强类型定义语言,动态类型定义语言 编译型语言 & 解释型语言 编译型语言:代码在执行前,需要编译(成机器语言文件,如 .exe 文件):以后再运行时,直接使用编译 ...

  3. DCL 数据控制语言

    目录 授予权限(GRANT) 回收权限(REVOTE) 授予权限(GRANT) # 语法 mysql> help grant; Name: 'GRANT' Description: Syntax ...

  4. 2017CCCC决赛 L1-3. 阅览室

    L1-3 阅览室(20 分) 天梯图书阅览室请你编写一个简单的图书借阅统计程序.当读者借书时,管理员输入书号并按下S键,程序开始计时:当读者还书时,管理员输入书号并按下E键,程序结束计时.书号为不超过 ...

  5. Leetcode(38)-报数

    报数序列是指一个整数序列,按照其中的整数的顺序进行报数,得到下一个数.其前五项如下: 1. 1 2. 11 3. 21 4. 1211 5. 111221 1 被读作  "one 1&quo ...

  6. window下安装docker教程

    Wi10系统下安装Docker 准备工作: 查看是否带有Hyper-V 1.第一步   2.第二步   第三步   第四步   第五步确认是否有Hyper-V(可以理解为windows自带虚拟机功能) ...

  7. Beacon API All In One

    Beacon API All In One Beacon API https://developer.mozilla.org/en-US/docs/Web/API/Beacon_API https:/ ...

  8. tree traversal

    tree traversal tree 遍历 中序,顺序,左中右 先序,先父节点,中左右 后序,先子节点,左右中 二叉搜索树 "use strict"; /** * * @auth ...

  9. UI 素材网站

    UI 素材网站 UI 设计师网站 国外: dribble.behance.Pinteres 国内: 优设.站酷.UI中国.花瓣 https://design.google/ https://dribb ...

  10. how to watch vuex state update

    how to watch vuex state update watch https://vuex.vuejs.org/api/#watch https://vuex.vuejs.org/guide/ ...