您的位置:首页 > 其它

POJ 1258 Agri-Net(最小生成树,模板题)

2013-10-17 09:43 483 查看
用的是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\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: