用的是prim算法。
我用vector数组,每次求最小的dis时,不需要遍历所有的点,只需要遍历之前加入到vector数组中的点(即dis[v]!=INF的点)。
但其实时间也差不多,和遍历所有的点的方法都是16ms。。。
#include <iostream> #include <algorithm> #include <string.h> #include <stdio.h> #include <string> #include <queue> using namespace std; const int INF=0x3f3f3f3f; int n,cost; int ans; int w[101][101]; int dis[101]; //生成树外的点与生成树相连的最短边长 int pre[101]; //pre[v]为v的前驱节点,用来输出进入最小生成树的边。该题用不到 int vis[101]; //标记点是否在生成树中 vector<int> son[101]; void init() { memset(pre,0,sizeof(pre)); memset(dis,INF,sizeof(dis)); memset(vis,0,sizeof(vis)); } int solve() { vector<int> node; int s=1,counts=0,ans=0,tmp,k; dis[s]=0; pre[s]=s; node.push_back(s); while(1) { tmp=INF; for(int i=0; i<node.size(); i++) { int v=node[i]; if(!vis[v]&& dis[v]<tmp) { tmp=dis[v]; k=v; //k即为在没有进入最小生成树的点中到树的距离(dis[k])最小的点。 } } /* //直接遍历所有的点 for(int i=1;i<=n;i++){ if(!vis[i]){ if(dis[i]<tmp){ tmp=dis[i]; k=i; } } } */ if(tmp==INF) break; ans+=tmp; vis[k]=1; for(int i=0; i<son[k].size(); i++) { int v=son[k][i]; if(!vis[v] && w[k][v]<dis[v]) { dis[v]=w[k][v]; pre[v]=k; node.push_back(v); } } } return ans; } int main() { while(scanf("%d",&n)!=EOF) { for(int i=0; i<101; i++) { son[i].clear(); } for(int i=1; i<=n; i++) { for(int j=1; j<=i; j++) scanf("%d",&cost); for(int j=i+1; j<=n; j++) { scanf("%d",&cost); w[i][j]=w[j][i]=cost; son[i].push_back(j); son[j].push_back(i); } } ans=0; init(); ans=solve(); printf("%d ",ans); } return 0; }