博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Luogu】P4208最小生成树计数(状压乱搞)
阅读量:5249 次
发布时间:2019-06-14

本文共 1479 字,大约阅读时间需要 4 分钟。

  

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

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

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

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

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

  最后乘法原理得到答案。

  

#include
#include
#include
#include
#include
#define maxn 10000#define mod 31011using namespace std;inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; 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
>=1; } return ans;}int ans[maxn];int pre[maxn];void copy(int x,int *a,int *b){ for(int i=1;i<=x;++i) a[i]=b[i];}int main(){ int n=read(),m=read(); for(int i=1;i<=m;++i) q[i]=(Edge){read(),read(),read()}; c.clear(n); sort(q+1,q+m+1,cmp); int cnt=0,last=0,now=0; for(int i=1;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]=1; sum[q[i].val]++; cnt++; if(cnt==n-1) break; } if(cnt

 

转载于:https://www.cnblogs.com/cellular-automaton/p/8794817.html

你可能感兴趣的文章
jquery 筛选器
查看>>
poj2255Tree Recovery【二叉树重构】
查看>>
(21)模型层 -ORM之msql 聚合查询,F和Q(与、或、非查询)、分组查询
查看>>
P3393 逃离僵尸岛
查看>>
Tomcat8配置用户名密码
查看>>
UNION ALL实现的分级汇总示例.sql
查看>>
理解线程池——外加一个Word模拟程序
查看>>
360-FAAR 0.4.3 发布,防火墙分析审计
查看>>
软件工程项目组Z.XML会议记录 2013/11/27
查看>>
tcpcopy 流量复制工具
查看>>
HttpClient 教程 (五)
查看>>
vue和react的区别
查看>>
PHP文件包含漏洞利用
查看>>
什么是动态规划?动态规划的意义是什么?
查看>>
document.documentElement和document.body区别介绍
查看>>
Cocos2d-x中Vector使用
查看>>
第十一次作业
查看>>
mybatis CRUD
查看>>
负载均衡策略
查看>>
Go 语言的基本数据类型
查看>>