• JoyOI1391 走廊泼水节


    一道另类生成树

    原题链接

    将输入的树的(n-1)条边按从小到大排序,然后(Kruskal)在生成该树的过程中计算新增边的总长。
    当在连第(i)条边,设该边的两端点为(x,y),长度为(z),分别属于(S_x)(S_y)两个并查集中。
    而为了将树变成完全图,显然要将(S_x,S_y)两个并查集中所有点一一连边,所以除去原有的这条边,剩下共(|S_x| imes|S_y|-1)条边需要被添加。
    而为了使完全图的最小生成树是原有树,所以在添加这(|S_x| imes|S_y|-1)条边时,必须使得这些边比原有边要长,同时由于要使得添加的边长和最小,所以这些边的长度均为(z+1)
    所以总长为((z+1) imes(|S_x| imes|S_y|-1)),将其累加至答案即可。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N = 6010;
    struct dd {
    	int x, y, z;
    };
    dd a[N];
    int fa[N], S[N];
    int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c<'0' || c>'9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0'&&c <= '9'; c = getchar())
    		x = x * 10 + (c - '0');
    	return p ? -x : x;
    }
    int fin(int x)
    {
    	if (fa[x] == x)
    		return x;
    	return fa[x] = fin(fa[x]);
    }
    int comp(dd x, dd y)
    {
    	return x.z < y.z;
    }
    int main()
    {
    	int i, x, y, n, t;
    	long long s;
    	t = re();
    	while (t--)
    	{
    		n = re();
    		for (S[n] = i = 1, fa[n] = n; i < n; i++)
    		{
    			a[i].x = re();
    			a[i].y = re();
    			a[i].z = re();
    			fa[i] = i;
    			S[i] = 1;
    		}
    		sort(a + 1, a + n, comp);
    		for (i = 1, s = 0; i < n; i++)
    		{
    			x = fin(a[i].x);
    			y = fin(a[i].y);
    			if (x != y)
    			{
    				s += 1LL * (a[i].z + 1)*(S[x] * S[y] - 1);
    				fa[x] = y;
    				S[y] += S[x];
    			}
    		}
    		printf("%lld
    ", s);
    	}
    	return 0;
    }
    
  • 相关阅读:
    MySQL 5.7 多主一从实现
    从 MySQL 全备的 SQL 文件中抽离出某张表的数据
    KUBERNETES 03:Pod 资源清单
    KUBERNETES 02:基本操作命令
    KUBERNETES 01:说明与安装
    DOCKER 08:搭建本地镜像仓库 Harbor
    DOCKER 07:docker swarm
    DOCKER 06:docker compose
    DOCKER 05:数据持久化
    DOCKER 04:容器资源限制和网络原理
  • 原文地址:https://www.cnblogs.com/Iowa-Battleship/p/9571573.html
Copyright © 2020-2023  润新知