求助!最后一个点TLE了,dijstra
查看原帖
求助!最后一个点TLE了,dijstra
416021
吃不饱QAQ楼主2022/8/3 05:06

没往最小生成树那边想,想了下dijstra发现正好能解决。

评测记录,前九个点还挺快,最后一个点T了。

#include<stdio.h>
#include<vector>
#include<math.h>
#define int long long//全是long long 
int cnt,head[1005],to[1005],ne[1005],x[1005],y[1005],q[1005],qq;
double ans[1005];
using namespace std;
void dfs(int a)
{
	int i;
	q[qq++]=a;//新的点放进q数组,之后会用到 
	ans[a]=0;//为零就表示访问过了 
	for(i=head[a];i;i=ne[i])
	if(ans[to[i]])
	dfs(to[i]);
}
signed main()
{
	int n,m,i,j,a,b,cu,min;
	double dis,sum=0;
	scanf("%lld%lld",&n,&m);
	for(i=1;i<=n;i++)
	scanf("%lld%lld",&x[i],&y[i]);
	for(i=0;i<m;i++)
	{
		scanf("%lld%lld",&a,&b);
		if(a==b)
		continue;
		cnt++;//链式前向星存图 
		ne[cnt]=head[a];
		to[cnt]=b;
		head[a]=cnt;
		cnt++;
		ne[cnt]=head[b];
		to[cnt]=a;
		head[b]=cnt;
	}
	for(i=1;i<=n+1;i++)//ans[i]为0表示已进入集合,否则表示已进入集合的点到第i个点最短的直线距离 
	ans[i]=(int)1<<63-1;
	cu=1;//从节点1开始 
	while(1)
	{
		qq=0;//qq记录了与cu连通且未在集合中的点的数量,这些点存在q数组中 
		dfs(cu);
		min=n+1;
		for(i=0;i<qq;i++)//i跑一遍所有新进入集合的点,计算节点i到其他所有未在集合中的节点的距离 
		for(j=1;j<=n;j++) 
		if(ans[j])//未在集合 
		{
			dis=sqrt((x[q[i]]-x[j])*(x[q[i]]-x[j])+(y[q[i]]-y[j])*(y[q[i]]-y[j]));
			if(dis<ans[j])//如果更优,就更新 
			ans[j]=dis;
		}
		for(i=1;i<=n;i++)
		if(ans[i]&&ans[i]<ans[min])//找一个未在集合且最优的,dijstra 
		min=i;
		if(min==n+1)//说明所有点都在集合里了,结束 
		break;
		sum+=ans[min];//把这条边加上 
		cu=min;
	}
	printf("%.2lf",sum);
}

时间复杂度应该是n2或者n*m

while(1)

for(i=0;i<qq;i++)

这俩复杂度相乘是n,因为第一个循环次数是连通分量的个数,第二个循环次数是每个连通分量里点的个数。

2022/8/3 05:06
加载中...