zoukankan      html  css  js  c++  java
  • P4208 [JSOI2008]最小生成树计数

    题目描述

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

    题解

    容易想到对于边权相同的那些边,选出来的边数是一定的,所以最终答案其实就是各个边权相同的部分的方案数的乘积,用并查集维护(dfs)即可,注意:由于有撤销操作,所以不能进行路径压缩。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int N = 1005;
    const int mod = 31011;
    int n, m, fa[N], cnt, tot, sum, ans = 1, now;
    struct node{int x, y, z;}a[N];
    struct data{int l, r, val;}e[N];
    inline int read()
    {
    	int x = 0, f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    bool cmp(const node & a, const node & b) {return a.z < b.z;}
    int find(int x) {return fa[x] == x ? x : find(fa[x]);}
    void dfs(int x, int goal, int num)
    {
    	if(x == goal + 1) {if(num == now) sum ++; return;}
    	int xx = find(a[x].x), yy = find(a[x].y);
    	if(xx != yy)
    	{
    		fa[xx] = yy; dfs(x + 1, goal, num + 1);
    		fa[xx] = xx; fa[yy] = yy;
    	}
    	dfs(x + 1, goal, num);
    }
    int main()
    {
    //	freopen("a.in", "r", stdin);
    //	freopen("a.out", "w", stdout);
    	n = read(); m = read();
    	for(int i = 1; i <= n; i ++) fa[i] = i;
    	for(int i = 1; i <= m; i ++) a[i].x = read(), a[i].y = read(), a[i].z = read();
    	sort(a + 1, a + m + 1, cmp);
    	for(int i = 1; i <= m; i ++)
    	{
    		if(a[i].z != a[i - 1].z) cnt ++, e[cnt].l = i, e[cnt - 1].r = i - 1;
    		int x = find(a[i].x), y = find(a[i].y);
    		if(x != y) {fa[x] = y; tot ++; e[cnt].val ++;}
    	}
    	e[cnt].r = m; if(tot != n - 1) {printf("0
    "); return 0;}
    	for(int i = 1; i <= n; i ++) fa[i] = i;
    	for(int i = 1; i <= cnt; i ++)
    	{
    		sum = 0; now = e[i].val; dfs(e[i].l, e[i].r, 0); ans = (ans * sum) % mod;
    		for(int j = e[i].l; j <= e[i].r; j ++)
    		{
    			int x = find(a[j].x), y = find(a[j].y);
    			if(x != y) fa[x] = y;
    		}
    	}
    	printf("%d
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    新安装的Apache和php,测试可以解析phpinfo,但是无法打开drupal网站
    Drupal7安装注意事项
    drupal7 为视图添加 过滤标准 内容类型
    Drupal网站报错:PDOException: in lock_may_be_available()
    窗口聚合函数与分组聚合函数的异同
    Linux环境下段错误的产生原因及调试方法小结(转)
    gzip 所使用压缩算法的基本原理(选摘)
    InfluxDB使用纪录
    子网掩码解释(转)
    列存的压缩原理学习
  • 原文地址:https://www.cnblogs.com/Sunny-r/p/12966803.html
Copyright © 2011-2022 走看看