现在给出了一个简单无向加权图。你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树。(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的)。由于不同的最小生成树可能很多,所以你只需要输出方案数对31011的模就可以了。

跑一遍克鲁斯卡尔,记录每种权值的边有多少条,然后状压枚举满足条件的所有边乘到答案中即可

/**************************************************************
Problem: 1016
User: walfy
Language: C++
Result: Accepted
Time:68 ms
Memory:1452 kb
****************************************************************/ //#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double g=10.0,eps=1e-;
const int N=+,maxn=+,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; struct edge{
int u,v,c;
bool operator<(const edge &rhs)const{
return c<rhs.c;
}
}e[N];
map<int,int>ans,id;
vector<pii>v[N];
int fa[N],prefa[N];
int Find(int x)
{
return fa[x]==x?x:fa[x]=Find(fa[x]);
}
int main()
{
fio;
int n,m;
cin>>n>>m;
for(int i=;i<=n;i++)fa[i]=i;
int cnt=;
for(int i=;i<m;i++)
{
int a,b,c;
cin>>a>>b>>c;
e[i]={a,b,c};
}
sort(e,e+m);
for(int i=;i<m;i++)
{
if(!id[e[i].c])id[e[i].c]=++cnt;
v[id[e[i].c]].pb(mp(e[i].u,e[i].v));
int x=e[i].u,y=e[i].v;
int fx=Find(x),fy=Find(y);
if(fx!=fy)fa[fx]=fy,ans[e[i].c]++;
}
for(int i=;i<=n;i++)
if(Find(i)!=Find(i-))
{
cout<<<<"\n";
return ;
}
for(int i=;i<=n;i++)fa[i]=i;
map<int,int>::iterator it=id.begin();
ll res=;
for(;it!=id.end();it++)
{
for(int i=;i<=n;i++)prefa[i]=fa[i];
// for(int i=0;i<v[it->se].size();i++)printf("%d %d %d\n",i,v[it->se][i].fi,v[it->se][i].se);
// puts("");
ll len=v[it->se].size(),go=-,pp=;
for(int i=;i<(<<len);i++)
{
int num=;
for(int j=;j<len;j++)
if((i>>j)&)
num++;
if(num!=ans[it->fi])continue;
else
{ bool ok=;
for(int j=;j<len;j++)
{
if((i>>j)&)
{
int x=v[it->se][j].fi,y=v[it->se][j].se;
int fx=Find(x),fy=Find(y);
if(fx!=fy)fa[fx]=fy;
else ok=;
}
}
if(ok)pp++,go=i;//,printf("%d\n",i);
}
for(int j=;j<=n;j++)fa[j]=prefa[j];
}
// printf("%d\n",pp);
res=(res*pp)%;
if(go==-)continue;
for(int j=;j<len;j++)
{
if((go>>j)&)
{
int x=v[it->se][j].fi,y=v[it->se][j].se;
int fx=Find(x),fy=Find(y);
if(x!=y)fa[fx]=fy;
}
}
}
cout<<res<<"\n";
return ;
}
/***********************
4 6 1 2 1 1 3 1 1 4 1 2 3 2 2 4 1 3 4 3
***********************/

bzo1016: [JSOI2008]最小生成树计数的更多相关文章

  1. bzoj1016 [JSOI2008]最小生成树计数

    1016: [JSOI2008]最小生成树计数 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 3517  Solved: 1396[Submit][St ...

  2. BZOJ 1016: [JSOI2008]最小生成树计数( kruskal + dfs )

    不同最小生成树中权值相同的边数量是一定的, 而且他们对连通性的贡献是一样的.对权值相同的边放在一起(至多10), 暴搜他们有多少种方案, 然后乘法原理. ----------------------- ...

  3. 1016: [JSOI2008]最小生成树计数

    1016: [JSOI2008]最小生成树计数 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 6200  Solved: 2518[Submit][St ...

  4. 【BZOJ 1016】 1016: [JSOI2008]最小生成树计数 (DFS|矩阵树定理)

    1016: [JSOI2008]最小生成树计数 Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树 ...

  5. 【bzoj1016】[JSOI2008]最小生成树计数

    1016: [JSOI2008]最小生成树计数 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 4863  Solved: 1973[Submit][St ...

  6. bzoj1016: [JSOI2008]最小生成树计数(kruskal+dfs)

    1016: [JSOI2008]最小生成树计数 题目:传送门 题解: 神题神题%%% 据说最小生成树有两个神奇的定理: 1.权值相等的边在不同方案数中边数相等  就是说如果一种方案中权值为1的边有n条 ...

  7. 【bzoj1016】 JSOI2008—最小生成树计数

    http://www.lydsy.com/JudgeOnline/problem.php?id=1016 (题目链接) 题意 求图的最小生成树计数. Solution %了下题解,发现要写矩阵树,15 ...

  8. [BZOJ]1016 JSOI2008 最小生成树计数

    最小生成树计数 题目描述 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同 ...

  9. 【BZOJ】1016: [JSOI2008]最小生成树计数 深搜+并查集

    最小生成树计数 Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小 ...

随机推荐

  1. 深度分析ORACLE热点块问题

    1.热点块的定义 数据库的热点块,从简单了讲,就是极短的时间内对 少量数据块进行了过于频繁的访问.定义看起来总是很简单的,但实际在数据库中,我们要去观察或者确定热点块的问题,却不是那么简单了.要深刻地 ...

  2. python 中元祖tuple的使用

    Python的元组与列表类似,不同之处在于元组的元素不能修改. 元组使用小括号,列表使用方括号. 元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可. eg,  tup1 = (1, 2, 3 ...

  3. Multiple encodings set for module chunk explatform "GBK" will be used by compiler

    项目用idea启动的时候,突然报了个这个 Multiple encodings set for module explatform "GBK" will be used by co ...

  4. javascript 类型 内存 对象

    var box =0 function test() { alert(box) //全局 }

  5. appium不同姿势安装

    一 桌面版(打开很慢,常用于辅助元素定位) 1.官网下载window版本: 2.直接点击图标即可打开  

  6. spark[源码]-Pool分析

    概述 这篇文章主要是分析一下Pool这个任务调度的队列.整体代码量也不是很大,正好可以详细的分析一下,前面在TaskSchedulerImpl提到大体的功能,这个点在丰富一下吧. DAGSchedul ...

  7. Linux中Qt的安装

    1.下载Ot安装包 Qt5.30的下载地址如下,在网页中打开找到需要的资源,下载.run格式的安装软件. http://download.qt.io/archive/qt/5.3/5.3.0/qt-o ...

  8. 20145313张雪纯 《Java程序设计》第3周学习总结

    20145313张雪纯 <Java程序设计>第3周学习总结 教材学习内容总结 4.1.1 定义类 package four; class Clothes{ String color; ch ...

  9. java类库字符串操作

    在java类库中,java给我们提供了字符串几个特别的操作,分别是String,Stringbuffer,Stringbuilder等.下面就对这几个类做一个简单的介绍.首先,我们先了解一下Strin ...

  10. 二进制转化 - bitset

    2017-08-28 10:55:17 writer:pprp 在之前写了一个关于bitset用法的贴之后,这是第一次运用,不得不说如果不用的话还是一头雾水 以后写代码要标记开始时间,和结束时间了,我 ...