求最小生成树两个算法
1、prim算法
首先设图G,点集V。
任取一个结点v1,加入最小生成树点集VT={v1},|VT|=k=1
在V-VT中选取某个vi∈VT邻接的结点vj,使得边(vi,vj)权最小,添加vj到VT,k++.
重复上一步直到k=|V|
(以下是通俗说法)
取一个起点,之后每次取一个点 使该点到已经取过的某一点的距离最小,直到所有点都取到为止。
此算法用邻接矩阵比较方便
2、kruskul算法
设图G,边集={e1,e2,e3......}
在G中选取最小权边e1,设i为已选取边数,i=1
while(i!=n-1)
{
在G中选取不同于已选边的最小权边ei,使它和已选边不构成回路
i++;
}
此算法用邻接表比较方便
先对边权排序,从小到大选择符合条件的合并,直到找到n-1条边为止。
hdu1233 还是畅通工程
#include <iostream> #include <cstring> #include <string> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <map> #define inf 0x3f3f3f3f #define ll __int64 using namespace std; int n,ans,vis[105],d[105],e[105][105]; void prim() { int i,j,tmp,p; memset(vis,0,sizeof vis); for(i=0;i<=n;i++) d[i]=e[1][i]; d[1]=0; for(i=1;i<=n;i++) { tmp=inf; for(j=1;j<=n;j++) { if(!vis[j]&&tmp>d[j]) { tmp=d[j]; p=j; } } vis[p]=1; for(j=1;j<=n;j++) { if(!vis[j]&&e[j][p]<d[j]) { d[j]=e[j][p]; } } } ans=0; for(i=1;i<=n;i++) ans+=d[i]; } int main() { int a,b,w,i; while(scanf("%d",&n)&&n) { int tmp=n*(n-1)/2; for(i=0;i<tmp;i++) { scanf("%d%d%d",&a,&b,&w); e[a][b]=e[b][a]=w; } prim(); printf("%d\n",ans); } return 0; }
hdu1863 畅通工程
#include <iostream> #include <cstring> #include <string> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <map> #define inf 0x3f3f3f3f #define ll __int64 using namespace std; struct node { int x,y,w; }e[5010]; int n,m,ans,r[105]; bool cmp(node a,node b) { return a.w<b.w; } int root(int a) { if(r[a]==a) return a; return r[a]=root(r[a]); } void kruskal() { int i,ra,rb,edge=0; for(i=0;i<m;i++) { ra=root(e[i].x); rb=root(e[i].y); if(ra==rb) continue; else { if(ra>rb) r[rb]=ra; else r[ra]=rb; ans+=e[i].w; edge++; if(edge==n-1) { printf("%d\n",ans); return; } } } printf("?\n"); return ; } int main() { int i; while(scanf("%d%d",&m,&n)&&m) { for(i=0;i<=n;i++) r[i]=i; for(i=0;i<m;i++) { scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w); } sort(e,e+m,cmp); ans=0; kruskal(); } return 0; }
#include <iostream> #include <cstring> #include <string> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <map> #define inf 0x3f3f3f3f #define ll __int64 using namespace std; struct node { int x,y; double w; }e[5050]; double ans; int n,m,r[110],x[110],y[110]; bool cmp(node a,node b) { return a.w<b.w; } double dis(int a,int b,int c,int d) { return sqrt(((a-c)*(a-c)+(b-d)*(b-d))*1.0); } int root(int a) { if(r[a]==a) return a; return r[a]=root(r[a]); } void kruskal() { int i,ra,rb,edge=0; for(i=0;i<n;i++) r[i]=i; for(i=0;i<m;i++) { ra=root(e[i].x); rb=root(e[i].y); if(ra==rb||e[i].w<10) continue; if(e[i].w>1000) break; else { if(ra>rb) r[rb]=ra; else r[ra]=rb; ans+=e[i].w; edge++; if(edge==n-1) { printf("%.1lf\n",ans*100); return ; } } } printf("oh!\n"); return; } int main() { int t,i,j; scanf("%d",&t); while(t--) { scanf("%d",&n); for(i=0;i<n;i++) scanf("%d%d",&x[i],&y[i]); m=0; for(i=0;i<n;i++) { for(j=i+1;j<n;j++) { e[m].x=i; e[m].y=j; e[m++].w=dis(x[i],y[i],x[j],y[j]); } } sort(e,e+m,cmp); ans=0; kruskal(); } return 0; }
hdu1879 继续畅通工程
#include <iostream> #include <cstring> #include <string> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <map> #define inf 0x3f3f3f3f #define ll __int64 using namespace std; struct node { int x,y,w; }e[5010]; int n,m,ans,r[110]; bool cmp(node a,node b) { return a.w<b.w; } int root(int a) { if(r[a]==a) return a; return r[a]=root(r[a]); } void merge(int a,int b) { int ra,rb; ra=root(a); rb=root(b); if(ra!=rb) r[ra]=rb; } void kruskal() { int i,ra,rb; for(i=0;i<m;i++) { ra=root(e[i].x); rb=root(e[i].y); if(ra==rb) continue; else { if(ra>rb) r[rb]=ra; else r[ra]=rb; ans+=e[i].w; } } return; } int main() { int tmp,a,b,c,d,i; while(scanf("%d",&n)&&n) { for(i=0;i<=n;i++) r[i]=i; int tmp=n*(n-1)/2; m=0; for(i=0;i<tmp;i++) { scanf("%d%d%d%d",&a,&b,&c,&d); if(d==1) merge(a,b); else { e[m].x=a; e[m].y=b; e[m++].w=c; } } sort(e,e+m,cmp); ans=0; kruskal(); printf("%d\n",ans); } return 0; }
最小生成树基础题目之畅通工程系列,布布扣,bubuko.com
原文:http://blog.csdn.net/u011032846/article/details/22087463