poj1258 AgriNet **

/*
* 纯粹的最短路 prim 用 二叉堆 实现
*
* 用二叉堆实现优先级队列 比较麻烦~ 后面附上直接用数组的
*
*/
#include
<cstdio>
#include
<cstring>
usingnamespace std;

constint maxN =100+5;
constint inf =100000000;
int n, G[maxN][maxN], len; //len:二叉堆数组的长度
int ans;
bool S[maxN];
int d[maxN], vertex[maxN], reverse[maxN]; //二叉堆中节点的域

int inline left(int i){ return2* i; }
int inline right(int i){ return2* i +1; }
int inline p(int i){ return i/2; }

void inline swap(int lhs, int rhs){
int tmp = d[lhs]; d[lhs] = d[rhs]; d[rhs] = tmp;
tmp
= vertex[lhs]; vertex[lhs] = vertex[rhs]; vertex[rhs] = tmp;
reverse[vertex[lhs]]
= lhs; reverse[vertex[rhs]] = rhs;
}

//二叉堆操作
void minHeapify(int i){
int l = left(i);
int r = right(i);

int tmpMinNum = i;
int tmpMinD = d[i];
if(l < len && d[l] < tmpMinD){
tmpMinNum
= l;
tmpMinD
= d[l];
}
if(r < len && d[r] < tmpMinD){
tmpMinNum
= r;
tmpMinD
= d[r];
}
if(tmpMinNum != i){
swap(i, tmpMinNum);
minHeapify(tmpMinNum);
}
}

void makeHeap(){
for(int i=0; i<n; i++){
d[i]
= inf; vertex[i] = reverse[i] = i;
}
d[
0] =0;

len
= n;
}

int minimumD(){ return d[0]; }
int minimumVertex() { return vertex[0]; }

int extractMin(){
int ans = minimumD();
swap(
0, len-1);
len
--;
minHeapify(
0);

return ans;
}

void decreaseKey(int i, int key){
d[i]
= key;
while(i !=0&& d[i] < d[p(i)]){
swap(i, p(i));
i
= p(i);
}
}

//MST-Prim
int mstPrim(){
makeHeap();

while(len !=0){
int minVertex = minimumVertex();
S[minVertex]
=1;
int tmp = extractMin();
ans
+= tmp;

for(int i=0; i<n; i++){
if(S[i] ==0&& G[i][minVertex] < d[reverse[i]]){
decreaseKey(reverse[i], G[i][minVertex]);
}
}
}
return ans;
}


int main(){
while(scanf("%d", &n) != EOF){
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
scanf(
"%d", &G[i][j]);

memset(S,
0, sizeof(S));
ans
=0;

mstPrim();

printf(
"%d\n", ans);
}



return0;
}

    

    

————————

    

 

/*
* STL priority_queue 实现
*
*/

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;

const int maxn = 100 + 5;
const int inf = 10000000;

int n, m[maxn][maxn];
int dis[maxn];
bool vis[maxn];

struct SNode{
int index;
int dis;

friend bool operator<(const SNode &a, const SNode &b){ //注意如何重载!!
//friend
return a.dis > b.dis;
}
};
SNode node[maxn];

int prim(){
int ans = 0;

for(int i=0; i<n; i++){
node[i].index = i;
node[i].dis = inf;
}
node[0].dis = 0;

priority_queue<SNode> q;
q.push(node[0]);

bool found = 0;
SNode cur;
for(int i=0; i<n; i++){
found = 0;
while(!q.empty()){
cur = q.top();
q.pop();

if(!vis[cur.index]){
found = 1;
break;
}
}

if(!found) break;

ans += cur.dis;

int v = cur.index;
vis[v] = 1; //别忘了更新vis
for(int j=0; j<n; j++){
if(!vis[j] && m[v][j] < node[j].dis){
node[j].dis = m[v][j];
q.push(node[j]);
}
}
}

return ans;
}

int main(){
while(scanf("%d", &n) == 1){
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
scanf("%d", &m[i][j]);
}
}

for(int i=0; i<n; i++)
dis[i] = inf;
memset(vis, 0, sizeof(vis));

int ans = prim();

printf("%d\n", ans);

}


return 0;
}

  

 ——————————   

      

#include<cstdio>
usingnamespace std;
constint Max =102;
constint inf =0xfffffff;


int n, ans;
int map[Max][Max], dis[Max]; // dis[i]表示顶点i与生成树之间的最短距离。


int min(int a, int b){
return a < b ? a : b;
}

void prim(){ // 自己的prim模板。
int i, j, now, min_node, min_edge;
for(i =1; i <= n; i ++)
dis[i]
= inf;
now
=1;
ans
=0;
for(i =1; i < n; i ++){
dis[now]
=-1; // 将dis[]的值赋-1,表示已经加入生成树中。
min_edge = inf;
for(j =1; j <= n; j ++) // 更新每个顶点所对应的dis[]值。
if(now != j && dis[j] >=0){
dis[j]
= min(dis[j], map[now][j]);
if(dis[j] < min_edge){
min_edge
= dis[j];
min_node
= j;
}
}
now
= min_node;
ans
+= min_edge;
}
}


int main(){
int i, j;
while(scanf("%d", &n) != EOF){
for(i =1; i <= n; i ++)
for(j =1; j <= n; j ++)
scanf(
"%d", &map[i][j]);
prim();
printf(
"%d\n", ans);
}
return0;
}
原文地址:https://www.cnblogs.com/longdouhzt/p/2163416.html