• CF745 C 并查集


    并查集
    由于政府不能连通
    我们可以先按给出的边建立连通块,再将不含有政府的点全部作为一个连通块,边数为(n-1)*n/2
    然后 贪心地将该连通块与[含政府的、且包含点数最多的]连通块相连,然后由于新增了一些点 所以记得要加上边
    最后减去初始边即可

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 100010;
    
    int fa[N];
    int siz[N];
    
    int find(int x)
    {
    	if(x != fa[x])
    		fa[x] = find(fa[x]);
    	return fa[x];
    }
    
    int join(int a, int b)
    {
    	int x = find(a);
    	int y = find(b);
    	if(x != y)
    	{
    		fa[x] = y;
    		siz[y] += siz[x];
    		return 1;
    	}
    	return 0;
    }
    
    int g[N];
    int vis[N];
    int sum[N];
    
    int main()
    {
    	int n, m, k;
    	while(cin >> n >> m >> k)
    	{
    		int cnt = 0;
    		for(int i = 0; i <= n; i++)
    			fa[i] = i, siz[i] = 1;
    		for(int i = 0; i < k; i++)
    			scanf("%d", g + i);
    		for(int i = 0; i < m; i++)
    		{
    			int x, y;
    			scanf("%d%d", &x, &y);
    			join(x, y);
    		}
    		for(int i = 0; i < k; i++)
    			vis[find(g[i])] = 1;
    
    		int ma = 0;
    		int ans = 0;
    		for(int i = 1; i <= n; i++)
    		{
    			if(find(i) == i)
    			{
    				if(vis[i] == 1)
    					ma = max(ma, siz[i]);
    				else sum[cnt++] = siz[i];
    				ans += ((siz[i] - 1) * siz[i]) / 2;
    			}
    		}
    		for(int i = 0; i < cnt; i++)
    			for(int j = i + 1; j < cnt; j++)
    				ans += sum[i] * sum[j];
    		int t = 0;
    		for(int i = 0; i < cnt; i++)
    			t += sum[i];
    		printf("%d
    ", ans + t*ma - m);
    	}
    }
    
  • 相关阅读:
    C# 删除指定目录下的所有文件及文件夹
    C# 数组集合分页 Skip Take
    MongoDB模糊查询 工具
    C# skip 重试执行代码段
    C# 加载配置文件
    消息队列MSMQ的使用
    C#中const和readonly的区别
    JSP页面中的tab页
    使用jquery获取单选按钮radio的值
    JSP页面获取下来框select选中项的值和文本的方法
  • 原文地址:https://www.cnblogs.com/Yumesenya/p/7449929.html
Copyright © 2020-2023  润新知