由于原来的模板在某些题目中出现了一些不可知的错误,我就把模板换了一个写法。

#include<bits/stdc++.h>
using namespace std;
int f[310][310];
int n,m,a,b,c,dis[310];
bool vis[310];
void prim()
{
    memset(dis,0x7f,sizeof(dis));    
    dis[1]=0;
    for(int i=1;i<=n;++i)
    {
        int k=0;
        for(int j=1;j<=n;j++)
            if(!vis[j]&&(dis[j]<dis[k])) k=j;
        vis[k]=1;
        for(int j=1;j<=n;j++)
            if(!vis[j] && f[k][j]!=0)
                dis[j]=min(dis[j],f[k][j]);
    }
}

主要的改动点有两处:
(1)原模板会先处理出第一个点对所有点dis的影响,而修改后选择将第一个点的影响划归到整个1~n的循环中处理
(2)原模板在循环末尾修改每个点k对所有点的dis值影响时,会不考虑已经被加入最小生成树中的点以及f[k][j]==0的点(含义是原图中不存在一条由k指向j的有向边)

附赠一道最小生成树的例题&题解
洛谷P2330 [SCOI2005]繁忙的都市
由题意可得,这个图里每两个点之间都最少有一条边相连,因此不用考虑超级原点的问题。所以这就是一道裸的最小生成树模板。其实看一下n和m的取值就能发现kruskal其实更优,但是prim也能过就是了~~

#include<bits/stdc++.h>
using namespace std;
const int maxn=305;
int maxx,dis[maxn],f[maxn][maxn],k,n,m;
bool vis[maxn];
void prim()
{
	memset(dis,0x3f,sizeof(dis));
	dis[1]=0;
	for(int i=1;i<=n;++i)
	{
		k=0;
		for(int j=1;j<=n;++j)
			if((!vis[j])&&(dis[j]<dis[k])) k=j;
		vis[k]=true;
		for(int j=1;j<=n;++j) 
			if(!vis[j]&&f[k][j]!=0) dis[j]=min(dis[j],f[k][j]);
	}
}
int main()
{
	int u,v,c;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;++i)
	{
		scanf("%d%d%d",&u,&v,&c);
		f[u][v]=c;
		f[v][u]=c;	
	}
	prim();
	n--;
	for(int i=1;i<=n;++i) maxx=max(maxx,dis[i]);
	printf("%d %d",n,maxx);
	return 0;
}

完结撒花(bushi