Prim 邻接矩阵版:
#define INF 0x3f3f3f3f const int MAXN = 105; int N; int map[MAXN][MAXN]; bool book[MAXN];//true为已经加入树的,false则相反 int lenth[MAXN];//注意有的博客这里解释为根到各个点的距离,其实应该是“树”到各个点的距离 int Prime() { memset(book,false,sizeof(book)); int sum = 0; book[0] = true;//这里选0点为根 for(int i=1 ; i<N ; i++) { lenth[i] = map[0][i];//刚开始集合就是0点 } for(int i=1 ; i<N ; i++) { int min = INF; int node; for(int j=1 ; j<N ; j++)//选出与“树”相连且权值最小的边 { if(book[j] == false && lenth[j]<min) { min = lenth[j]; node = j; } } sum += min; book[node] = true;//把新的点加入树中 for(int i=1 ; i<N ; i++)//根据新加入的点更新“树”到其他点的距离。 { if(book[i] == false && lenth[i]>map[node][i]) { lenth[i] = map[node][i]; } } } return sum;//返回结果 }
Prim 邻接表版:
const int MAXN = 1005; const int INF = 0x3f3f3f3f; int N,M,W; struct Edge{ int to; int value; int next; }E[MAXN*MAXN]; int head[MAXN]; int top; void Add(int from,int to,int value){//邻接表加入边函数 E[++top].next = head[from]; head[from] = top; E[top].value = value; E[top].to = to; } bool book[MAXN]; int lenth[MAXN]; int prim(){ memset(book,false,sizeof book); memset(lenth,0,sizeof lenth); book[1] = true; int ans = 0; for(int i=head[1] ; i ; i=E[i].next){ lenth[E[i].to] = E[i].value; } int minL = INF;//与“树”相连且权值最小的边的权值。 int mint;//与“树”相连且边权值最小的点的下标。 for(int i=2 ; i<=N ; i++){//因为以第一个点为根,所以只需要再找N-1个点就够了。 for(int j=2 ; j<=N ; j++){ //第一个点已经确定,所以每次从第二个点开始找。 if(book[j] == false && lenth[j]<minL){ minL = lenth[j]; mint = j; } } ans += minL; minL = INF; book[mint] = true; for(int k=head[mint] ; k ; k=E[k].next){ if(book[E[k].to] == false && lenth[E[k].to] > E[k].value)lenth[E[k].to] = E[k].value; } } return ans; } void init(){//初始化函数,有需要在每组输入之前进行处理的都可以加到这里。 memset(head,0,sizeof head); top = 0; }
Kruskal 邻接表版:
const int MAXN = 1005; int N,M;//点数;边数。 int pre[MAXN];//记录点的祖先 struct Edge{//边结构体 int from; int to; int value; Edge(){} Edge(int a,int b,int c):from(a),to(b),value(c){} }; struct cmp{ bool operator()(struct Edge a,struct Edge b){ return a.value > b.value; } }; priority_queue<struct Edge,vector<struct Edge>,cmp> Q;//存边的优先队列 int Find(int a){ if(pre[a] == a)return a; return pre[a] = Find(pre[a]); } bool Judge(int a,int b){ int A = Find(a); int B = Find(b); if(A != B){ pre[A] = B; return true; } return false; } int Num,Sum;//表示已经找到的边数;表示最小生成树的值。 void init(){//初始化函数,有需要在每组输入之前进行处理的都可以加到这里。 Sum = Num = 0; for(int i=1 ; i<=N ; i++)pre[i] = i;//初始化祖先为自己。 while(!Q.empty())Q.pop(); //清空优先队列 } int main(){ int a,b,c; while(scanf("%d %d",&N,&M)!=EOF){ init(); for(int i=0 ; i<M ; i++){ scanf("%d %d %d",&a,&b,&c); Q.push(Edge(a,b,c)); } while(!Q.empty() && Num<N-1){//找N-1条边就够了。 if(Judge(Q.top().from,Q.top().to)){ Sum += Q.top().value; ++Num; } Q.pop(); } printf("%d\n",Sum); } return 0; }