题目链接

  最小生成树有两个性质,两个性质都知道的话这题就变成码农题了。

  1、无论最小生成树长什么样,所有权值的边的数量是不变的。比如我有棵最小生成树有两条权值为2的边四条权值为1的边,那这个图的所有最小生成树都是两条权值为2的边四条权值为1的边。

  2、无论最小生成树长什么样,把边从小到大排序,某一权值的边连完后,联通块一定是固定的。

  这就提示了我们先求一遍最小生成树,得到生成树里每个权值的边都有几条,然后枚举权值,状压当前权值选的边集,看能不能把选出来的这些边都摁进森林里去。如果能的话该权值的连接方案数就+1.

  枚举完之后,因为第二条所以我们直接把所有该权值的边的两个端点合到一个并查集里就好了。

  最后乘法原理得到答案。

  

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<cstdlib>
#define maxn 10000
#define mod 31011
using namespace std;
inline long long read(){
long long num=,f=;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-;
ch=getchar();
}
while(isdigit(ch)){
num=num*+ch-'';
ch=getchar();
}
return num*f;
} struct Edge{
int from,to,val;
}edge[maxn],q[maxn],d[maxn];
bool cmp(Edge a,Edge b){ return a.val<b.val; }
int head[maxn],num;
inline void add(int from,int to,int val){
edge[++num]=(Edge){head[from],to,val};
head[from]=num;
} bool vis[maxn];
int sum[maxn];
int w[maxn];
int size;
struct fus{
int father[maxn];
inline void clear(int n){ for(int i=;i<=n;++i) father[i]=i; }
int find(int x){
if(father[x]!=x) father[x]=find(father[x]);
return father[x];
}
inline void unionn(int x,int y){
x=find(x); y=find(y);
father[y]=x;
}
}c,r,right; inline int getlen(int x){
int ans=;
while(x){
if(x&) ans++;
x>>=;
}
return ans;
} int ans[maxn];
int pre[maxn]; void copy(int x,int *a,int *b){ for(int i=;i<=x;++i) a[i]=b[i];} int main(){
int n=read(),m=read();
for(int i=;i<=m;++i) q[i]=(Edge){read(),read(),read()};
c.clear(n);
sort(q+,q+m+,cmp);
int cnt=,last=,now=;
for(int i=;i<=m;++i){
//离散化
now=q[i].val;
if(q[i].val==last) q[i].val=size;
else q[i].val=++size;
last=now; int from=q[i].from,to=q[i].to;
if(c.find(from)==c.find(to)) continue;
c.unionn(from,to);
vis[q[i].val]=;
sum[q[i].val]++;
cnt++;
if(cnt==n-) break;
}
if(cnt<n-){
printf("");
return ;
}
c.clear(n);
cnt=;
int maxval=;
for(int i=;i<=m;++i)
if(vis[q[i].val]){
d[++cnt]=q[i];
w[q[i].val]++;
maxval=max(maxval,q[i].val);
}
last=;
for(int i=;i<=maxval;++i){
int Max=<<w[d[last+].val];
copy(n,right.father,c.father);
for(int j=;j<Max;++j){
if(getlen(j)!=sum[d[last+].val]) continue;
bool flag=;
copy(n,r.father,c.father);
for(int k=;(<<k)<=j;++k)
if(j&(<<k)){
int ret=(k+)+last;
if(r.find(d[ret].from)==r.find(d[ret].to)){
flag=;
break;
}
r.unionn(d[ret].from,d[ret].to);
}
if(flag==){
ans[d[last+].val]++;
copy(n,right.father,r.father);
}
}
copy(n,c.father,right.father);
last+=w[d[last+].val];
}
for(int i=;i<=maxval;++i)
if(w[i]){
last=i;
break;
}
for(int i=last;i<=maxval;++i){
if(ans[i]&&i!=last){
ans[i]=(ans[i]*ans[last])%mod;
last=i;
}
}
printf("%d\n",ans[last]);
return ;
}

【Luogu】P4208最小生成树计数(状压乱搞)的更多相关文章

  1. [BZOJ1494][NOI2007]生成树计数 状压dp 并查集

    1494: [NOI2007]生成树计数 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 793  Solved: 451[Submit][Status][ ...

  2. luogu 2704 炮兵阵地 状压dp

    状压的基础题吧 第一次看感觉难上天,后来嘛就.. 套路:先根据自身状态筛出可行状态,再根据地图等其他限制条件筛选适合的状态加入答案 f i,j,k 分别代表 行数,本行状态,上行状态,再累加答案即可 ...

  3. HDU5117 Fluorescent 期望 计数 状压dp 动态规划

    原文链接https://www.cnblogs.com/zhouzhendong/p/HDU5117.html 题目传送门 - HDU5117 题意 $T$ 组数据. 给你 $n$ 盏灯 ,$m$ 个 ...

  4. Luogu 3959 [NOIP2017] 宝藏- 状压dp

    题解 真的想不到这题状压的做法...听说还有跑的飞快的模拟退火,要是现场做绝对滚粗QAQ. 不考虑深度,先预处理出 $pt_{i, S}$ 表示让一个不属于 集合 $S$ 的 点$i$ 与点集 $S$ ...

  5. Luogu P1134 阶乘问题 【数学/乱搞】 By cellur925

    输入输出格式 输入格式: 仅一行包含一个正整数 NN . 输出格式: 一个整数,表示最右边的非零位的值. 输入输出样例 输入样例#1: 12 输出样例#1: 6 说明 USACO Training S ...

  6. [CSP-S模拟测试]:统计(树状数组+乱搞)

    题目传送门(内部题120) 输入格式 第一行,两个正整数$n,m$. 第二行,$n$个正整数$a_1,a_2,...,a_n$,保证$1\leqslant a_i\leqslant n$,可能存在相同 ...

  7. BZOJ 1012: [JSOI2008]最大数maxnumber 单调队列/线段树/树状数组/乱搞

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 4750  Solved: 2145[Submi ...

  8. hdu 5094 状压bfs+深坑

    http://acm.hdu.edu.cn/showproblem.php?pid=5094 给出n*m矩阵 给出k个障碍,两坐标之间存在墙或门,门最多10种,状压可搞 给出s个钥匙位置及编号,相应的 ...

  9. hdu 1429 bfs+状压

    题意:这次魔王汲取了上次的教训,把Ignatius关在一个n*m的地牢里,并在地牢的某些地方安装了带锁的门,钥匙藏在地牢另外的某些地方.刚开始 Ignatius被关在(sx,sy)的位置,离开地牢的门 ...

随机推荐

  1. 洛谷 P2827 蚯蚓

    题目描述 本题中,我们将用符号\lfloor c \rfloor⌊c⌋表示对c向下取整,例如:\lfloor 3.0 \rfloor= \lfloor 3.1 \rfloor=\lfloor 3.9 ...

  2. 使用nodejs消费SAP Cloud for Customer上的Web service

    Jerry在公众号文章C4C和微信集成系列教程里曾经使用nodejs去消费C4C提供的标准webservice. 看一个具体例子:C4C里Individual Customers可以维护Social ...

  3. codeforce Gym 100570B ShortestPath Query (最短路SPFA)

    题意:询问单源最短路径,每条边有一个颜色,要求路径上相邻边的颜色不能相同,无重边且边权为正. 题解:因为路径的合法性和边的颜色有关, 所以在做spfa的时候,把边丢到队列中去,松弛的时候注意判断一下颜 ...

  4. 第008课_第1个ARM落版程序及引申

    form:第008课_第1个ARM裸板程序及引申 第001节_辅线1_硬件知识_LED原理图 当我们学习C语言的时候,我们会写个Hello程序.那当我们下ARM程序,也该有一个简单的程序引领我们入门, ...

  5. ES6学习笔记(二)

    Set 和 Map 数据结构 1.set 基本用法 ES6提供了新的数据结构Set,它类似于数组,但是成员的值都是唯一的,没有重复的值 Set本身是一个构造函数,用来生成Set数据结构 const s ...

  6. MFC多文档无法显示可停靠窗格

    当我们使用MFC多文档创建项目时,我们可停靠窗格关闭之后就无法显示了.即使重新编译项目也无法再次显示它们. 原因:因为MFC多文档把这些设置存储在注册表 “HKEY_CURRENT_USER \ SO ...

  7. Cordova 本地项目创建方法

    l  创建项目 需要在终端上输入:cordova create [目录][项目ID][APP名称] 运行:cordova create hello com.example.hello hello 将在 ...

  8. C++ 学习笔记(二) const的加强

    const 含义为只读.如果在程序中显式改变const变量那么编译会报错. C语言的const: 在C语言中const 变量是放在内存中,如果使用指针可以间接改变const变量.所以在C语言中cons ...

  9. tempfs详解

    致因 在平常工作中,我们经常需要查看Linux服务器磁盘挂载使用情况,可以使用df命令,不知大家注意到没有,我们使用此命令除了会查看到系统盘以及数据盘挂载情况,还会看到一个tmpfs也在挂载. [ro ...

  10. 记一次低级错误导致的mysql(111)

    今天下午配好的双主多从服务器,两台主机+主机内安装好的6台虚拟机,两台Mysql master各授权好其slave的远程登录,原本好端端的能远程登录,晚上回来时候就发现其中一台master登录不上其s ...