• P5687 网格图


    算法原理

    根据 (operatorname{Kruskal}) 算法的运算规则,每次总是会把当前边权最小,且连接着本不连通的两个点的边选中。

    而在这道题目中,位于同一行或列的边的边权大小一定是相同的,因此一定会接连选完这一行或列上所有可行的边。

    思考过程

    选择一行/列后,整个被选中的行/列上所有的点都位于同一个连通分量。

    故选完至少一行和至少一列后,接下来构成生成树的过程中,一定保证只存在一个包含两个及以上节点的连通分量。

    这是一个关键点,思考过程可以以这个点分成两部分。

    1. 在选完至少一行和一列之前,保证接下来选择的任何行/列,这一行/列上所有的边都会被选择。

    2. 而在选完至少一行和一列之后,对于即将被选择的一行来说,这一行上尚未被连接进最小生成树的点的个数 (=) 总的列数 (-) 已被选择的列数。而一条边在构建最小生成树时,只能将一个点与最小生成树连接起来。因此选择这一行能选择的边的条数,即等于这一行上尚未接入最小生成树的点的个数。即总列数 (-) 已被选择的列数。对于列来说同理。

    因此总的算法思路就明确了:

    1. 首先将所有的边权值放到一起升序排列,注意记录一下这个边权是横边的边权还是纵边的边权,开一个 pair 存很方便(自动按照第一关键字为索引进行升序排序)。一遍 sort 进行排序。开两个变量 (l ext{(line)})(c ext{(column)}) 存储已经选择的行/列数。

    2. 然后从小到大枚举排序后的边权,在两个统计变量都不为 (0) 之前,任何选的行/列都将其所包含的所有边全部加入最小生成树。

    3. 在两个统计变量都大于 (0) 之后,对于行来说,加入其包括的 (m-c) 条边,即可保证这一行上所有的点全部加入最小生成树,且不会影响到之后的选择,故可以保证正确性。列同理。

    Tips

    • 排序时把所有的边放在了一起,因此记得把数组开成两倍。
    • 不开 long long 见祖宗

    代码:

    #include<bits/stdc++.h>
    
    #define LL long long
    
    using namespace std;
    
    const int Maxe = 3e5 + 5;
    pair<LL, bool> a[Maxe << 1];
    int n, m;
    LL ans = 0;
    int main()
    {
    	scanf("%d%d", &n, &m);
    	for(register int i = 1; i <= n; ++i)
    	{
    		int x;
    		scanf("%d", &x);
    		a[i] = make_pair(x, false);
    	}
    	for(register int i = n + 1; i <= n + m; ++i)
    	{
    		int x;
    		scanf("%d", &x);
    		a[i] = make_pair(x, true);
    	}
    	sort(a + 1, a + n + m + 1);
    	int l = 0, c = 0;
    	for(register int i = 1; i <= n + m; ++i)
    	{
    		if(!a[i].second)
    		{
    			if((!l)||(!c))
    			{
    				ans += (long long)(m - 1) * a[i].first;
    			}
    			else
    			{
    				ans += (long long)(m - c) * a[i].first;
    			}
    			l++;
    		}
    		else
    		{
    			if((!l)||(!c))
    			{
    				ans += (long long)(n - 1) * a[i].first;
    			}
    			else
    			{
    				ans += (long long)(n - l) * a[i].first;
    			}
    			c++;
    		}
    	}
    	printf("%lld", ans);
    	return 0;
    }
    
  • 相关阅读:
    多线程中的静态代理模式
    ARP报文
    静态链表代码
    顺序表中的思路
    数据结构与算法
    我是见鬼了吗?这是史上最邪恶的脚本!没有之一
    细说"回车"和"换行"的故事
    SVN版本控制系统搭建(结合http服务)
    cooike和session到底是个啥
    Python3中 if __name__=='__main__'是个什么意思
  • 原文地址:https://www.cnblogs.com/zimujun/p/13679891.html
Copyright © 2020-2023  润新知