一、题目

点此看题

二、解法

这道题很离谱啊,看上去是求一个最大值,其实是把生成树权值为 \(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. VS2010下如何查看类的内存布局

    用VS2010查看类的内存布局,这里用两种方法 (1)MSVC有个隐藏的"/d1"开关,通过这个开关可以查看项目中类的内存布局情况. 修改项目属性,添加"/d1 repo ...

  2. C# 类 (8) - 抽象方法

    抽象 抽象方法 只能 定义在抽象类 里,并且抽象方法里没有具体的代码,像这种 为啥要定义一个空空如也的函数呢?这是为了用来约束 它的派生类 的行为, 这个例子,建立了一个数组,放了cat和dog,这两 ...

  3. 006.NET 项目建立+传值

    1. 创建项目 2.传值(控制器向视图传递) 接收值 3.视图向控制器传递 4.session配置

  4. NoSQL 数据库案例实战 -- MongoDB数据备份、恢复

    MySQL数据迁移到MongoDB数据库中 前言 一.数据备份 二.数据恢复 前言 本环境是基于 Centos 7.8 系统构建mongodb-enterprise-4.2.8学习环境具体构建,请参考 ...

  5. 2021 从零开始打造一个自己的 UI 组件库

    2021 从零开始打造一个自己的 UI 组件库 refs GUI https://github.com/xgqfrms/gui/ https://www.npmjs.com/package/@xgqf ...

  6. JavaScript 词法 All In One

    JavaScript 词法 All In One JavaScript 词法 这部分描述了JavaScript 的词法(lexical grammar). ECMAScript 源码文本会被从左到右扫 ...

  7. React 性能优化 All In One

    React 性能优化 All In One Use CSS Variables instead of React Context https://epicreact.dev/css-variables ...

  8. node.js 中间件

    node.js 中间件 node.js middleware Express middleware body-parser cookie-parser cookie-session cors csur ...

  9. gitpod & free online ide

    gitpod & free online ide Dev Environments as Code for modern DevOps teams. https://www.gitpod.io ...

  10. taro & Error: spawn taro ENOENT

    taro & Error: spawn taro ENOENT https://stackoverflow.com/questions/27688804/how-do-i-debug-erro ...