[CSP-S2019 江西] 网格图

image

 

Sol 

其实就是求最小生成树,但不同的是,这是一个网格图。

拿样例来说

image

 

可以对所有横向边升序排列得到2 3 4

再对纵向边升序列排列得到1 2 3

易知横向边的最小值2,及纵向边的最小值1是必须要选的。

选出来后,会得到下图

image

 我们记h代表纵向的点,目前取走了多少个

L代表横向的点,取走了多少个

对于横坐标升序排成2 3 4

纵坐标升序排成1 2 3

我们用两个指针来查找接下来的最小边

发现纵向的2是最小的,并且可以选取了条数为N-H,于是得到下图

image

 加完这一列后,则L++。。。。。这个地方要想清楚,因为这些点即在列上,也是行上。

接下来我们要加的边为横向的边长为3的边,并且此时就只能加一条了,而不能加2条,否则就会成环,不是MST了。

image

 

最后加一条纵向的长度为3的边,并且也是只能加1条,得到下图

image

 

#include<bits/stdc++.h>
using namespace std;
inline int read()
{	int x=0;
	bool f=0;
	char c=getchar();
	while(!isdigit(c))f|=(c=='-'),c=getchar();
	while(isdigit(c))x=x*10+(c&15),c=getchar();
	return f?-x:x;
}
int n,m,a[300005],b[300005];
long long ans;//不开long long见祖宗。 
int main()
{	n=read(),m=read();
	for(register int i=1;i<=n;i++)
	a[i]=read();
	for(register int i=1;i<=m;i++)
	b[i]=read();
	sort(a+1,a+n+1);
	sort(b+1,b+m+1);
	ans=(long long)a[1]*(m-1)+(long long)b[1]*(n-1);
	cout<<"ans is  "<<ans<<endl;
	//首先将最小的一行 和 最小的一列加上。 
	int cnta=2,cntb=2,h=1,l=1;
	//h代表纵向上,共有N个点,目前已加了多少个点
	//L代表横向上,共有M个点,目前加了多少个点 
	while(cnta<=n&&cntb<=m)
	//双指针来找最小值 
	{	if(a[cnta]<=b[cntb]) //加上横向边 
	    {
	      ans+=(long long)a[cnta]*(m-l);
	      cout<<"add it1  "<<a[cnta]<<"   "<<m-l<<endl;
	      cout<<"add it1  ans is  "<<ans<<endl;
		  cnta++;
		  h++; //注意是h++ 
	      
	    }
		else //加上纵向上的图 
		{
		    ans+=(long long)b[cntb]*(n-h);
		    cout<<"add it2  "<<b[cntb]<<"   "<<n-h<<endl;
		    cout<<"add it2  ans is  "<<ans<<endl;
		    cntb++;
		    l++; //注意是l++ 
	    }
	}
	printf("%lld\n",ans);
	return 0;
}

  

 

posted @ 2025-09-08 16:17  我微笑不代表我快乐  阅读(14)  评论(0)    收藏  举报