666 专题十一 最小生成树
Problem A.Jungle Roads
d.
s.没什么好说的,最小生成树
c.
/* Kruskal算法 Kruskal算法求MST */ #include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int MAXN=110;//最大点数 const int MAXM=10000;//最大边数 int F[MAXN];//并查集使用 struct Edge{ int u,v,w; }edge[MAXM];//存储边的信息,包括起点/终点/权值 int tol;//边数,加边前赋值为0 void addedge(int u,int v,int w){ edge[tol].u=u; edge[tol].v=v; edge[tol++].w=w; } //排序函数,将边按照权值从小到大排序 bool cmp(Edge a,Edge b){ return a.w<b.w; } int find(int x){ if(F[x]==-1)return x; else return F[x]=find(F[x]); } //传入点数,返回最小生成树的权值,如果不连通返回-1 int kruskal(int n){ memset(F,-1,sizeof(F)); sort(edge,edge+tol,cmp); int cnt=0;//计算加入的边数 int ans=0; for(int i=0;i<tol;i++){ int u=edge[i].u; int v=edge[i].v; int w=edge[i].w; int t1=find(u); int t2=find(v); if(t1!=t2){ ans+=w; F[t1]=t2; cnt++; } if(cnt==n-1)break; } if(cnt<n-1)return -1;//不连通 else return ans; } int main(){ int n; char str[2]; char str2[2]; int k; int w; while(~scanf("%d",&n)){ if(n==0)break; tol=0; for(int i=0;i<n-1;++i){ scanf("%1s%d",str,&k); for(int j=0;j<k;++j){ scanf("%1s%d",str2,&w); addedge(str[0]-'A',str2[0]-'A',w); } } printf("%d\n",kruskal(n)); } return 0; }
Problem B.Networking
c.
/* Prim算法 Prim求MST 耗费矩阵cost[][],标号从0开始,0~n-1 返回最小生成树的权值,返回-1表示原图不连通 */ #include<iostream> #include<stdio.h> #include<string.h> using namespace std; const int INF=0x3f3f3f3f; const int MAXN=110; bool vis[MAXN]; int lowc[MAXN]; //点是 0 n-1 int Prim(int cost[][MAXN],int n){ int ans=0; memset(vis,false,sizeof(vis)); vis[0]=true; for(int i=1;i<n;i++)lowc[i]=cost[0][i]; for(int i=1;i<n;i++){ int minc=INF; int p=-1; for(int j=0;j<n;j++) if(!vis[j]&&minc>lowc[j]){ minc=lowc[j]; p=j; } if(minc==INF)return -1;//原图不连通 ans+=minc; vis[p]=true; for(int j=0;j<n;j++) if(!vis[j]&&lowc[j]>cost[p][j]) lowc[j]=cost[p][j]; } return ans; } int main(){ int cost[MAXN][MAXN]; int P,R; int u,v,w; while(~scanf("%d",&P)){ if(P==0)break; for(int i=0;i<P;++i){ for(int j=0;j<P;++j){ cost[i][j]=INF; } } scanf("%d",&R); for(int i=0;i<R;++i){ scanf("%d%d%d",&u,&v,&w); --u;--v; if(w<cost[u][v]){ cost[u][v]=cost[v][u]=w; } } printf("%d\n",Prim(cost,P)); } return 0; }
Problem C.Building a Space Station
c.
/* Prim算法 Prim求MST 耗费矩阵cost[][],标号从0开始,0~n-1 返回最小生成树的权值,返回-1表示原图不连通 */ #include<iostream> #include<stdio.h> #include<string.h> #include<math.h> using namespace std; const double INF=1e10; const int MAXN=110; bool vis[MAXN]; double lowc[MAXN]; //点是 0 n-1 double Prim(double cost[][MAXN],int n){ double ans=0; memset(vis,false,sizeof(vis)); vis[0]=true; for(int i=1;i<n;i++)lowc[i]=cost[0][i]; for(int i=1;i<n;i++){ double minc=INF; int p=-1; for(int j=0;j<n;j++) if(!vis[j]&&minc>lowc[j]){ minc=lowc[j]; p=j; } if(minc==INF)return -1;//原图不连通 ans+=minc; vis[p]=true; for(int j=0;j<n;j++) if(!vis[j]&&lowc[j]>cost[p][j]) lowc[j]=cost[p][j]; } return ans; } int main(){ double cost[MAXN][MAXN]; int n; double x[MAXN],y[MAXN],z[MAXN],r[MAXN]; double len1,len2; while(~scanf("%d",&n)){ if(n==0)break; for(int i=0;i<n;++i){ for(int j=0;j<n;++j){ cost[i][j]=INF; } } for(int i=0;i<n;++i){ scanf("%lf%lf%lf%lf",&x[i],&y[i],&z[i],&r[i]); } for(int i=0;i<n;++i){ for(int j=0;j<n;++j){ len1=sqrt( (x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]) + (z[i]-z[j])*(z[i]-z[j]) ); len2=r[i]+r[j]; if(len2>len1){ cost[i][j]=cost[j][i]=0; } else{ cost[i][j]=cost[j][i]=len1-len2; } } } printf("%.3f\n",Prim(cost,n)); } return 0; }
Problem L.还是畅通工程
hint.题解见以前
Problem N.畅通工程再续
hint.题解见以前