【BZOJ】1016 生成树计数 最小生成树 Maxtrix-Tree定理 生成树计数 搜索
2015-09-19 21:15
429 查看
题目大意:给出一个简单无向加权图,求最小生成树有多少种?
首先最小生成树有以下两个性质:
(1)每种权值相同的边的数量是一定的。
(2)权值相同的边对最小生成树的效果相同。
那么首先求一次最小生成树,找出每种边的数量。
然后枚举权值,可以进行搜索或者用Matrix-Tree定理用行列式进行生成树计数。
根据乘法原理相乘即结果。
搜索:
小结:(1)最小生成树的两个性质
首先最小生成树有以下两个性质:
(1)每种权值相同的边的数量是一定的。
(2)权值相同的边对最小生成树的效果相同。
那么首先求一次最小生成树,找出每种边的数量。
然后枚举权值,可以进行搜索或者用Matrix-Tree定理用行列式进行生成树计数。
根据乘法原理相乘即结果。
搜索:
/************************************************************** Problem: 1016 User: y20070316 Language: C++ Result: Accepted Time:8 ms Memory:1304 kb ****************************************************************/ #include <bits/stdc++.h> using namespace std; const int N=128; const int M=1024; const int MOD=31011; int n,m; int f ; struct Edge { int u,v,d; }e[M]; struct List { int id; int nxt; }ud_list[M]; int hd[M],tt,num; int cnt[M]; int res=1,sum; inline int Read(void) { int s=0,f=1; char c=getchar(); for (;!isdigit(c);c=getchar()) if (c=='-') f=-1; for (;isdigit(c);c=getchar()) s=s*10+c-'0'; return s*f; } inline int operator < (Edge ea,Edge eb) { return ea.d<eb.d; } inline void InsList(int w,int id) { ud_list[++tt].id=id; ud_list[tt].nxt=hd[w]; hd[w]=tt; } int Find(int i) { return f[i]==i?i:Find(f[i]); } void DFS(int k,int dep,int goal) { if (dep==goal) {sum++;return;} if (!k) return; int fu=Find(e[ud_list[k].id].u),fv=Find(e[ud_list[k].id].v); if (fu!=fv) { f[fu]=fv; DFS(ud_list[k].nxt,dep+1,goal); f[fu]=fu,f[fv]=fv; } DFS(ud_list[k].nxt,dep,goal); } int main(void) { n=Read(),m=Read(); for (int i=1;i<=m;i++) e[i].u=Read(),e[i].v=Read(),e[i].d=Read(); int tmp=0; sort(e+1,e+m+1); for (int i=1;i<=m;i++) { if (e[i].d!=tmp) num++; tmp=e[i].d; e[i].d=num; InsList(num,i); } int fu,fv,totc=0; for (int i=1;i<=n;i++) f[i]=i; for (int i=1;i<=m;i++) { fu=Find(e[i].u),fv=Find(e[i].v); if (fu==fv) continue; cnt[e[i].d]++,totc++,f[fu]=fv; } if (totc!=n-1) {printf("0\n");return 0;} for (int i=1;i<=n;i++) f[i]=i; for (int i=1;i<=num;i++) { sum=0; DFS(hd[i],0,cnt[i]); res=res*sum%MOD; for (int k=hd[i];k;k=ud_list[k].nxt) { fu=Find(e[ud_list[k].id].u),fv=Find(e[ud_list[k].id].v); if (fu!=fv) f[fu]=fv; } } printf("%d\n",res); return 0; }
小结:(1)最小生成树的两个性质
相关文章推荐
- 游戏开发观念又转变了-需要学习更多
- LintCode Majority Number II / III
- Camera显示之Hal层的适配
- 无锁编程 - 大纲
- AVL树,红黑树,B树,B+树,Trie树应用场景简介
- java 编程IDE-eclipse使用基础问题
- 项目开发指引
- 无锁编程 - 大纲
- 【poj2104】K-th Number 分块
- hiho1087 Hamiltonian Cycle 位运算+记忆化搜索 求哈密顿回路数量
- 函数指针和指针函数
- POJ 1502 水 dij
- sp<> 强指针类的用法
- 【五校联考2015 9.19】C
- 从网络解析数据并实现三个界面的跳转
- iOS 应用开发,用户密码存储技术--KeyChain
- 微博分享坑
- android studio 使用库
- SQL语句
- HDU 5461 沈阳网络赛