首页 > 代码库 > BZOJ 1016 JSOI 2008 最小生成树计数 Kruskal+搜索
BZOJ 1016 JSOI 2008 最小生成树计数 Kruskal+搜索
题目大意:给出一些边,求出一共能形成多少个最小生成树。
思路:最小生成树有很多定理啊,我也不是很明白,这里只简单讲讲做法,关于定各种定理请看这里:http://blog.csdn.net/wyfcyx_forever/article/details/40182739
我们先做一次最小生成树,然后记录每一种长度的边有多少在最小生成树中,然后从小到大搜索,看每一种边权有多少种放法,然后所有的都算出来累乘就是最终的结果。
CODE:
#include <map> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 2010 #define MO 31011 using namespace std; map<int,int> G; struct Complex{ int x,y,len; bool operator <(const Complex &a)const { return len < a.len; } void Read() { scanf("%d%d%d",&x,&y,&len); } }edge[MAX]; int points,edges; int ones[MAX]; int father[MAX]; int ans = 1; void Pretreatment() { for(int i = 1;i <= 1025; ++i) ones[i] = ones[i >> 1] + (i&1); } int Find(int x) { if(!father[x] || father[x] == x) return father[x] = x; return father[x] = Find(father[x]); } bool Kruskal() { int cnt = 0; for(int i = 1;i <= edges; ++i) { int fx = Find(edge[i].x); int fy = Find(edge[i].y); if(fx != fy) { father[fy] = fx; G[edge[i].len]++; cnt++; } } if(cnt < points - 1) return false; return true; } void DFS(int pos) { if(pos > edges) return ; int st = pos,ed = pos,re = 0; int cnt = G[edge[st].len]; if(!cnt) { DFS(ed + 1); return ; } while(edge[ed + 1].len == edge[st].len) ++ed; for(int i = 0;i < (1 << (ed - st + 1)); ++i) if(ones[i] == cnt) { memset(father,0,sizeof(father)); int temp = i; for(int j = st; temp; temp >>= 1,++j) if(temp&1) { int fx = Find(edge[j].x); int fy = Find(edge[j].y); if(fx == fy) break; father[fy] = fx; } if(!temp) ++re; } ans = (ans * re) % MO; memset(father,0,sizeof(father)); for(int i = st; i <= ed; ++i) { int fx = Find(edge[i].x); int fy = Find(edge[i].y); if(fx == fy) continue; father[fy] = fx; } for(int i = ed + 1;i <= edges; ++i) edge[i].x = Find(edge[i].x),edge[i].y = Find(edge[i].y); DFS(ed + 1); } int main() { Pretreatment(); cin >> points >> edges; for(int i = 1;i <= edges; ++i) edge[i].Read(); sort(edge + 1,edge + edges + 1); memset(father,0,sizeof(father)); if(!Kruskal()) { cout << 0 << endl; return 0; } DFS(1); cout << ans << endl; return 0; }
BZOJ 1016 JSOI 2008 最小生成树计数 Kruskal+搜索
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。