现在给出了一个简单无向加权图。你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树。(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的)。由于不同的最小生成树可能很多,所以你只需要输出方案数对31011的模就可以了。
现在给出了一个简单无向加权图。你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树。(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的)。由于不同的最小生成树可能很多,所以你只需要输出方案数对31011的模就可以了。
第一行包含两个数,n和m,其中1<=n<=100; 1<=m<=1000; 表示该无向图的节点数和边数。每个节点用1~n的整数编号。接下来的m行,每行包含两个整数:a, b, c,表示节点a, b之间的边的权值为c,其中1<=c<=1,000,000,000。数据保证不会出现自回边和重边。注意:具有相同权值的边不会超过10条。
输出不同的最小生成树有多少个。你只需要输出数量对31011的模就可以了。
暴力大法好。。。
对于最小生成树,同一种权值边使用次数一样
因为在两种方案里若同种权值边使用次数不同,必有一种更优
然后每种边不超过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); #endif cin >> 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; }