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

来源:互联网 发布:base64 js 源码 编辑:程序博客网 时间:2024/05/19 15:41

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

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 4162  Solved: 1673
[Submit][Status][Discuss]

Description

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

Input

第一行包含两个数,n和m,其中1<=n<=100; 1<=m<=1000; 表示该无向图的节点数和边数。每个节点用1~n的整数编号。接下来的m行,每行包含两个整数:a, b, c,表示节点a, b之间的边的权值为c,其中1<=c<=1,000,000,000。数据保证不会出现自回边和重边。注意:具有相同权值的边不会超过10条。

Output

输出不同的最小生成树有多少个。你只需要输出数量对31011的模就可以了。

Sample Input

4 6
1 2 1
1 3 1
1 4 1
2 3 2
2 4 1
3 4 1

Sample Output

8

HINT

Source

[Submit][Status][Discuss]



暴力大法好。。。


对于最小生成树,同一种权值边使用次数一样

因为在两种方案里若同种权值边使用次数不同,必有一种更优

然后每种边不超过10条

每种爆搜即可


#include<iostream>#include<cstdio>#include<cstdlib>#include<algorithm>#include<cstring>#include<cmath>#include<vector>#include<queue>using namespace std;typedef long long LL;const LL mo = 31011;const int maxn = 1E2 + 10;const int maxm = maxn*10;struct E{int u,v,w;bool operator < (const E&b) const {return w < b.w;}}e[maxn*10];int n,m,cur = 1,fa[maxn],use[maxm],num[maxm];int a[maxm],po;LL ans = 1,sum;int father(int k){return k == fa[k]?k:father(fa[k]);}void dfs(int x,int tot){if (x == a[po]+1) {if (tot == use[po]) ++sum; return;}if (a[po] - x + 1 + tot < use[po]) return;int fu = father(e[x].u);int fv = father(e[x].v);if (fu != fv) {fa[fu] = fv;dfs(x+1,tot+1);fa[fu] = fu;}dfs(x+1,tot);}int main(){#ifdef YZY   freopen("yzy.txt","r",stdin);#endifcin >> n >> m;for (int i = 1; i <= m; i++) {int u,v,w;scanf("%d%d%d",&u,&v,&w);e[i] = (E){u,v,w};num[i] = w;}for (int i = 1; i <= n; i++) fa[i] = i;sort(e+1,e+m+1);sort(num+1,num+m+1);for (int i = 2; i <= m; i++)if (num[i] != num[i-1])num[++cur] = num[i]; int tot = 0;for (int i = 1; i <= m; i++) {int fu = father(e[i].u);int fv = father(e[i].v);int pos = lower_bound(num+1,num+cur+1,e[i].w) - num;if (fu != fv) {fa[fu] = fv;++tot;++use[pos];}if (e[i].w != e[i-1].w) a[pos-1] = i-1;}a[cur] = m;if (tot != n-1) {cout << 0;return 0;}for (int i = 1; i <= n; i++) fa[i] = i;for (int i = 1; i <= m; i++)if (e[i].w != e[i-1].w) {sum = 0;po = lower_bound(num+1,num+cur+1,e[i].w) - num;dfs(i,0);ans = ans*sum%mo;for (int j = i; j <= a[po]; j++) {int fu = father(e[j].u);int fv = father(e[j].v);if (fu != fv) fa[fu] = fv;}}cout << ans;return 0;}


1 0