Problem Description
XXX is very interested in algorithm. After learning the
Prim algorithm and Kruskal algorithm of minimum spanning tree, XXX finds that
there might be multiple solutions. Given an undirected weighted graph with n
(1<=n<=100) vertexes and m (0<=m<=1000) edges, he wants to know the
number of minimum spanning trees in the graph.
 
Input
There are no more than 15 cases. The input ends by 0 0
0.
For each case, the first line begins with three integers --- the above
mentioned n, m, and p. The meaning of p will be explained later. Each the
following m lines contains three integers u, v, w (1<=w<=10), which
describes that there is an edge weighted w between vertex u and vertex v( all
vertex are numbered for 1 to n) . It is guaranteed that there are no multiple
edges and no loops in the graph.
 
Output
For each test case, output a single integer in one line
representing the number of different minimum spanning trees in the graph.
The
answer may be quite large. You just need to calculate the remainder of the
answer when divided by p (1<=p<=1000000000). p is above mentioned, appears
in the first line of each test case.
Sample Input
5 10 12
2 5 3
2 4 2
3 1 3
3 4 2
1 2 3
5 4 3
5 1 3
4 1 1
5 3 3
3 2 3
0 0 0
 
Sample Output
4
 
Source
 
 
题意:求最小生成树的数量
 
矩阵树定理
 
回想 Kruskal算法,从小到大枚举边
当边权相等时,边随意排序
那么当权值为k的边全部枚举完后,点的联通情况F是固定的
也就是说权值都为k的边无论以什么顺序枚举,得到的生成树的形态不一,但联通情况F'和F相同
如果将加入最小生成树的 权值为1——k-1的边 和 对应的点 压缩成一个点,
所有权值为k 的边 的联通情况 是独立的
根据乘法原理
我们可以枚举权值k
计算此时形成F的方案数 
具体来说就是 枚举权值为k的边形成的连通块,用矩阵树定理算出每种连通块的方案数
累乘就是权值为k的边形成F的方案数
最后将所有权值为k的边的答案累乘
 
注意 并查集不要路径压缩
因为矩阵树定理需要每个点的度数

#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,mod;
int fa[],ka[];
struct node
{
int u,v,w;
}e[];
int a[][];
bool vis[];
vector<int>g[];
long long ans,C[][],t;
bool cmp(node p,node q)
{
return p.w<q.w;
}
int find(int i,int *f) { return f[i]==i ? i : find(f[i],f); }
bool init()
{
int u,v;
scanf("%d%d%d",&n,&m,&mod);
if(!n) return false;
for(int i=;i<=m;i++) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
return true;
}
long long det(int h)
{
long long s=;
for(int i=;i<h;i++)
{
for(int j=i+;j<h;j++)
while(C[j][i])
{
t=C[i][i]/C[j][i];
for(int k=i;k<h;k++) C[i][k]=(C[i][k]-C[j][k]*t+mod)%mod;
for(int k=i;k<h;k++) swap(C[i][k],C[j][k]);
s=-s;
}
s=s*C[i][i]%mod;
if(!s) return ;
}
return (s+mod)%mod;
}
void matrix_tree()
{
int len,u,v;
for(int i=;i<=n;i++)
if(vis[i])
{
g[find(i,ka)].push_back(i);
vis[i]=false;
}
for(int i=;i<=n;i++)
if(g[i].size())
{
memset(C,,sizeof(C));
len=g[i].size();
for(int j=;j<len;j++)
for(int k=j+;k<len;k++)
{
u=g[i][j]; v=g[i][k];
if(a[u][v])
{
C[k][j]=(C[j][k]-=a[u][v]);
C[k][k]+=a[u][v]; C[j][j]+=a[u][v];
}
}
ans=ans*det(g[i].size()-)%mod;
for(int j=;j<len;j++) fa[g[i][j]]=i;
}
for(int i=;i<=n;i++)
{
g[i].clear();
ka[i]=find(i,fa);
}
}
void solve()
{
ans=;
int u,v;
memset(a,,sizeof(a));
for(int i=;i<=n;i++) fa[i]=ka[i]=i;
sort(e+,e+m+,cmp);
for(int i=;i<=m+;i++)
{
if(e[i].w!=e[i-].w && i!= || i==m+) matrix_tree();
u=find(e[i].u,fa); v=find(e[i].v,fa);
if(u!=v)
{
vis[u]=vis[v]=true;
ka[find(u,ka)]=find(v,ka);
a[u][v]++; a[v][u]++;
}
}
bool flag=true;
for(int i=;i<n && flag;i++)
if(find(i,fa)!=find(i+,fa)) flag=false;
printf("%lld\n",flag ? ans%mod : );
}
int main()
{
while(init()) solve();
}

 
 

hdu 4408 Minimum Spanning Tree的更多相关文章

  1. HDU 4408 Minimum Spanning Tree 最小生成树计数

    Minimum Spanning Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  2. 【HDU 4408】Minimum Spanning Tree(最小生成树计数)

    Problem Description XXX is very interested in algorithm. After learning the Prim algorithm and Krusk ...

  3. 多校 HDU - 6614 AND Minimum Spanning Tree (二进制)

    传送门 AND Minimum Spanning Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 ...

  4. 数据结构与算法分析–Minimum Spanning Tree(最小生成树)

    给定一个无向图,如果他的某个子图中,任意两个顶点都能互相连通并且是一棵树,那么这棵树就叫做生成树(spanning tree). 如果边上有权值,那么使得边权和最小的生成树叫做最小生成树(MST,Mi ...

  5. Educational Codeforces Round 3 E. Minimum spanning tree for each edge LCA/(树链剖分+数据结构) + MST

    E. Minimum spanning tree for each edge   Connected undirected weighted graph without self-loops and ...

  6. CF# Educational Codeforces Round 3 E. Minimum spanning tree for each edge

    E. Minimum spanning tree for each edge time limit per test 2 seconds memory limit per test 256 megab ...

  7. Codeforces Educational Codeforces Round 3 E. Minimum spanning tree for each edge LCA链上最大值

    E. Minimum spanning tree for each edge 题目连接: http://www.codeforces.com/contest/609/problem/E Descrip ...

  8. MST(Kruskal’s Minimum Spanning Tree Algorithm)

    You may refer to the main idea of MST in graph theory. http://en.wikipedia.org/wiki/Minimum_spanning ...

  9. [Educational Round 3][Codeforces 609E. Minimum spanning tree for each edge]

    这题本来是想放在educational round 3的题解里的,但觉得很有意思就单独拿出来写了 题目链接:609E - Minimum spanning tree for each edge 题目大 ...

随机推荐

  1. ThinkPHP - 1 - 本地部署

    ThinkPHP ThinkPHP是一个快速.简单的基于MVC和面向对象的轻量级PHP开发框架,遵循Apache2开源协议发布,从诞生以来一直秉承简洁实用的设计原则,在保持出色的性能和至简的代码的同时 ...

  2. 2.重新安装CM服务

    步骤1.停止CM服务2.删除CM服务3.添加CM服务4.测试数据库 步骤 1.停止CM服务 2.删除CM服务 没有发现可以单独删除某一项CM服务,必须全部删除 3.添加CM服务 4.测试数据库 如果报 ...

  3. 【转】Hbuilder MUI 页面刷新及页面传值问题

    文章来源:http://www.111cn.net/sys/CentOS/67213.htm 一.页面刷新问题 1.父页面A跳转到子页面B,B页面修改数据后再跳回A页面,刷新A页面数据 (1).父页面 ...

  4. AndroidUI设计之 布局管理器 - 详细解析布局实现

    写完博客的总结 : 以前没有弄清楚的概念清晰化 父容器与本容器属性 : android_layout...属性是本容器的属性, 定义在这个布局管理器的LayoutParams内部类中, 每个布局管理器 ...

  5. DAY6敏捷冲刺

    站立式会议 工作安排 (1)服务器配置 服务器端项目结构调整 (2)数据库配置 单词学习记录+用户信息 (3)客户端 客户端项目结构调整,代码功能分离 燃尽图 燃尽图有误,已重新修改,先贴卡片的界面, ...

  6. Java容器之Iterator接口

    Iterator 接口: 1. 所有实现了Collection接口的容器类都有一个iterator方法用以返回一个实现了Iterator接口的对象. 2. Iterator 对象称作迭代器,用以方便的 ...

  7. java线程安全— synchronized和volatile

    java线程安全— synchronized和volatile package threadsafe; public class TranditionalThreadSynchronized { pu ...

  8. iOS- AVSpeechSynthesizer——iOS7语音合成器

    语音合成器的技术是iOS7推出的,可以实现无网络语音功能,支持多种语言 1. 定义一个成员变量,记录语音合成器 AVSpeechSynthesizer #import <AVFoundation ...

  9. 数据库集群之路二 MYCAT

    windows下安装配置并使用mycat 参考:http://www.cnblogs.com/parryyang/p/5758087.html 一 下载windows版本 https://github ...

  10. 【Linux】- rm命令

    Linux rm命令用于删除一个文件或者目录. 语法 rm [options] name... 参数: -i 删除前逐一询问确认. -f 即使原档案属性设为唯读,亦直接删除,无需逐一确认. -r 将目 ...