poj-1258 Agri-Net **
/*
* 纯粹的最短路 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;
}