253 jungle roads
就是一道MST的模板题。求出最小生成树后算出所有边的和。
Kruskal算法使用的是并查集(merge ,find)对于该算法需要构建edge结构体,对edge进行排序。
prim算法模板
//Prim做法 : 维护一个MST点集合,每次纳入MST点集内和点集外相连的最短边
//使用edge的优先队列pq
//也可以不用优先队列pq,这样就类似于dijkstra算法中的vis[],d[]数组的数据结构
struct edge{ //因为使用了pq,所以需要构建edge结构体
int u,v,cost;
edge(int _u,int _v,int _cost):u(_u),v(_v),cost(_cost){}
edge(){}
};
struct cmp{ //创建结构体,用于pq的比较运算符
bool operator ()(const edge & a,const edge& b){
return a.cost>b.cost;
}
};
int n;
//使用邻接矩阵,但感觉应该使用邻接表(邻接矩阵还需要判断M[i][j]是否存在边M[i][j]==-1
int M[50][50];
int used[50] //使用数组即可,不用使用set判断是否属于点集
int main(){
memset(M,-1,sizeof(M));
memset(used,0,sizeof(used));
/*
输入
*/
priority_queue<edge,vector<edge>,cmp> pq;
//初始化pq ,节点的下标从1开始
for(int i=1;i<=n;i++){
if(M[1][i]!=-1)
pq.push(edge(1,i,M[i][1])); //edge()中第一条边表示加入集合中的边
}
used[1]=1;
int res=0; //统计MST的边之和
int edgcnt=0;
while(true){ //找到n-1条边即可
edge e=pq.top(); //pq是用top()!!!
pq.pop();
int tu=e.u,tv=e.v,tcost=e.cost;
if(!used[tv]){
used[tv]=1;
res+=tcost;
edgcnt++;
for(int j=1;j<=n;j++){
if(!used[j]&&M[tv][j]!=-1)//要排除等于-1(节点之间没有边)的情况
pq.push(edge(tv,j,M[tv][j]));
}
}
if(edgcnt==n-1) break;
}
cout<<res<<endl;
}