Prim和Kruskal 思路 模版
最小生成树概念
构造连通网的最小代价生成树
Prim算法
思路
图表示
所需
一个二维数组图,一个记录访问的数组,一个保存最小距离的数组,一个可活动的点。
模版代码
查看原题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| #include <iostream> using namespace std; int main(int argc, char *argv[]) { int n,m,c1,c2,cost,low[105],map[105][105]; while(cin>>n>>m&&n){ int total=0; for(int i=1;i<=m;i++){ for(int j=1;j<=m;j++){ if(i==j)map[i][j]=0; else map[i][j]=999999; } } for(int i=1;i<=m;i++){ low[i]=999999; } while(n--){ cin>>c1>>c2>>cost; if(cost<map[c1][c2]){ map[c1][c2]=map[c2][c1]=cost; } } low[1]=0; for(int i=1;i<=m;i++){ low[i]=map[1][i]; } for(int i=1;i<m;i++){ int least=999999,leastnumber=0; for(int j=1;j<=m;j++){ if(low[j]<least&&low[j]!=0){ least=low[j]; leastnumber=j; } } if(leastnumber!=0){ low[leastnumber]=0; total+=least; for(int k=1;k<=m;k++){ if(map[leastnumber][k]<low[k]){ low[k]=map[leastnumber][k]; } } } } int flag=1; for(int i=1;i<=m;i++){ if(low[i]==999999){ flag=0; break; } } if(flag==0)cout<<"?"<<endl; else cout<<total<<endl; } return 0; }
|
Kruskal
思路
从所有边中依次选择代价最小的,如果该边上的顶点未被收录,将该边加入,否则舍去选择下一条,直到所有点都被收录为止。
图表示
模版代码
查看原题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| #include <iostream> #include <stdio.h> #include <algorithm> using namespace std; const int N=1005; const int M=N*N; int num[N][N]; int father[M]; struct Edge{ int u,v,w; }edge[2*M]; int cmp(Edge a,Edge b){ return a.w<b.w; } int find(int x){ if(x!=father[x]){ father[x]=find(father[x]); } return father[x]; } int Kruskal(int id){ sort(edge+1,edge+id,cmp); int cost=0; for(int i=1;i<id;i++){ int x=find(edge[i].u); int y=find(edge[i].v); if(x!=y){ father[x]=y; cost+=edge[i].w; } } return cost; } int main(){ int t,n,m; cin>>t; for(int loop=1;loop<=t;loop++){ scanf("%d %d",&n,&m); for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ father[i*m+j]=i*m+j; scanf("%d",&num[i][j]); } } int id=1; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ int u=i*m+j; if(i>0){ int v=(i-1)*m+j; edge[id].u=u; edge[id].v=v; edge[id++].w=abs(num[i][j]-num[i-1][j]); } if(j>0){ int v=i*m+j-1; edge[id].u=u; edge[id].v=v; edge[id++].w=abs(num[i][j]-num[i][j-1]); } } } int cost=Kruskal(id); cout<<"Case #"<<loop<<":"<<endl; cout<<cost<<endl; } return 0; }
|