LiuChip_ssy @ 2021-09-01 21:13:19
#include<bits/stdc++.h>
using namespace std;
int fread()
{
char ch=getchar();
int x=0,flag=1;
while(ch>'9'||ch<'0')
{
if(ch=='-') flag=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*flag;
}//快读
const int maxn=2e5+1;//最大边数
struct node
{
bool vis;//是否被访问
int dis;//到这个点的最小距离
int parent;//距离这个点距离最小的点
int linked;//这个点连接别的点的个数
}num[maxn];//数字个数
int n,m,dis1[5001][5001],start=INT_MAX;//n是点数,m是边数,dis1存储n到m的距离,start表示起点
void init()//初始化
{
fill(dis1[0],dis1[0]+5001*5001,INT_MAX);//所有距离均为不可达
for(int i=0;i<maxn;i++)
{
num[i].vis=false;//所有点均未被访问
num[i].dis=INT_MAX;//所有最大距离均为不可达
num[i].parent=-1;//所有的上一个距离最短的连接点均为-1
num[i].linked=0;//所有点的连接数均为0
}
return;
}
int cnt=0,sum=0;//最小总边权
void prim(int x)//更新
{
for(int i=start+1;(!(x<start)&&!(x>=start+n)&&!(num[x].linked==0))
&&i<start+n;i++)//判断i这个点是否在图内
{
if(num[i].vis) continue;//判断这个点是否被访问
if(dis1[x][i]<num[i].dis)//更新最短距离
{
num[i].dis=dis1[x][i];
num[i].parent=x;
}
}
int nxt=INT_MAX;//下一次递归的点
int fa=INT_MAX;//距离下一次递归的点距离最近的点
int minx=INT_MAX;//最短的距离
for(int j=start;j<start+n;j++)
{
if(num[j].vis) continue;//判断是否已被访问
if(num[j].dis<minx)//找到最短距离
{
minx=num[j].dis;//更新最短距离
nxt=j;//更新下一次递归的(也就是作为起点的)点
fa=num[j].parent;//更新fa
}
}
if(minx!=INT_MAX)
{
cnt+=minx;
sum++;
}//更新最小总边权
else return;//如果不可达就返回
num[start].vis=true;//起点访问记录改为true
num[nxt].vis=true;//下一个点访问记录改为true
prim(nxt);//递归
return;
}
int main()
{
n=fread(),m=fread();//快读输入点和边的个数
init();//初始化
for(int i=1;i<=m;i++)
{
int temp1=fread(),temp2=fread(),temp3=fread();//读入边
start=min(start,min(temp1,temp2));//找到编号最小的点
dis1[temp1][temp2]=dis1[temp2][temp1]=min(dis1[temp1][temp2],temp3);//添加边
num[temp1].linked++;//连接数+1
num[temp2].linked++;//连接数+1
}
prim(start);//从起点开始递归
if(sum<n-1)//如果边数小于n-1则不能生成最小生成树,输出orz
{
printf("orz");
return 0;
}
printf("%d",cnt);//否则输出最小总边权
return 0;//结束
}
我这里写的是Prim算法,代码的注释也写的很清楚了,但是时间特别长(1.89s),空间也特别大(99.46MB)。可以问下如何优化吗?
by LiuChip_ssy @ 2021-09-01 21:16:02
当时想的是:如果他周边的距离都是不可达或者有可达的点但是点都被访问了,这种情况下来判断点是否在图内。但是无论如何我也没有办法实现,所以就加了那个linked。而且我的prim模板是自己摸索出来的,比大神们的写的要长的多。
by KAMIYA_KINA @ 2021-09-01 21:19:59
你以后考场上不会想写 prim 的,相信我。
能写 kruscal 就写 kruscal。
by LiuChip_ssy @ 2021-09-02 21:53:48
@KAMIYA_KINA 哦哦哦好的,感谢大佬指导~