大家都知道最小生成树有两种算法:prim(普利姆)———从点考虑,kruskal(克鲁斯卡)————从边考虑
初学最小生成树时,看的这篇博文,感觉棒棒哒点击打开链接
hdu 1233 最小生成树
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#define N 100100
using namespace std;
struct node{
int a,b,c;
}mapp[N];
int fa[N];
int com(node t1,node t2){
return t1.c<t2.c;///按权重小的将边排序
}
///并查集查找每个点的父亲节点来判断两点是否都已经加入新图中以及判断图是否连通
int findfa(int x){
if(x!=fa[x])
fa[x]=findfa(fa[x]);
return fa[x];
}
int main(){
int n,m,i,fx,fy,res;
while(scanf("%d",&n)!=EOF&&n){
m=n*(n-1)/2;
res=0;
for(i=1;i<=n;i++) fa[i]=i;
for(i=1;i<=m;i++)
scanf("%d %d %d",&mapp[i].a,&mapp[i].b,&mapp[i].c);
sort(mapp+1,mapp+m+1,com);
for(i=1;i<=m;i++){
fx=findfa(mapp[i].a); fy=findfa(mapp[i].b);
if(fx!=fy){///若附近节点不同,就把它两之间的边加入新图中
fa[fx]=fy;///并且使其中任意一方的父亲节点更新成另一方的父亲节点
res+=mapp[i].c;
--n;
}
}
printf("%d\n",res);
}
return 0;
}
hdu 1162
<span style="font-size:14px;">普莱姆算法 prim</span>
#include<stdio.h>
#include <string.h>
#include<stdlib.h>
#include <math.h>
#include <algorithm>
using namespace std;
int mark[11000],n;
double mapp[11000][11000],dist[11000],left[11000],right[11000];
///函数也要变类型
double prim(){
int i,j,k;
double sum=0.0,min;
for(i=0;i<n;i++)
dist[i]=mapp[0][i];
dist[i]=0,mark[0]=1;
for(i=1;i<n;i++){
min=1542487693.00,k=-1;//这里的min也要变成double类型
for(j=0;j<n;j++)
if(dist[j]<min&&mark[j]==0){
min=dist[j];
k=j;
}
mark[k]=1;
if(k==-1) break;
else{
sum+=dist[k];
for(j=0;j<n;j++)
if(mark[j]==0&&mapp[k][j]<dist[j])
dist[j]=mapp[k][j];
}
}
return sum;
}
int main()
{
int i,j,k;
double ans=0.0;
while(scanf("%d",&n)!=EOF){
memset(mark,0,sizeof(mark));
for(i=0;i<n;i++)
scanf("%lf %lf",&left[i],&right[i]);//注意是double类型的
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(i!=j){
mapp[i][j]=sqrt((left[i]-left[j])*(left[i]-left[j])+(right[i]-right[j])*(right[i]-right[j]));
mapp[j][i]=mapp[i][j];
}
ans=prim();
printf("%.2f\n",ans);
}
return 0;
}
克鲁斯卡算法 kruskal
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int m,per[500];
struct node {
int x,y;
double dis;//注意类型
}s[10000000];
double cmp(node x,node y)
{
return x.dis<y.dis;
}
int find(int x)
{
/*非递归法查找父亲结点
int i=x,t=x,j;
while(t!=per[t])
t=per[t];
while(i!=t)
{
j=per[i];
per[i]=t;
i=j;
}
return t;
*/
if(x!=per[x])
per[x]=find(per[x]);
return per[x];
}
int main()
{
int i,j,t,fx,fy;;
double a[500],b[500],sum;
while(scanf("%d",&m)!=EOF){
for(i=0;i<m;i++) per[i]=i;
for(i=0;i<m;i++)
scanf("%lf %lf",&a[i],&b[i]);
t=0;sum=0.0;
for(i=0;i<m;i++)
{
for(j=0;j<i;j++)
{
s[t].x=i;
s[t].y=j;
double q=(sqrt((a[i]-a[j])*(a[i]-a[j])+(b[i]-b[j])*(b[i]-b[j])*1.0));
///if(q<=1000&&q>=10)
s[t++].dis=q;
}
}
sort(s,s+t,cmp);
for(i=0;i<t;i++)
{
fx=find(s[i].x),fy=find(s[i].y);
if(fx!=fy){
per[fx]=fy;
sum+=s[i].dis;
}
}
printf("%.2f\n",sum);
}
return 0;
}
hdu 1102
#include <iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
#define Y 0x3f3f3f3f
#define N 11100000
using namespace std;
int n,mapp[350][350],dist[350],mark[350];
int prim(){
memset(mark,0,sizeof(mark));
int i,j,minn,k,sum=0;
for(i=1;i<=n;i++)
dist[i]=mapp[1][i];
dist[1]=0,mark[1]=1;
for(i=1;i<n;i++){
minn=Y,k=-1;
for(j=1;j<=n;j++)
if(mark[j]==0&&dist[j]<minn){
minn=dist[j];
k=j;
}
mark[k]=1;
if(k==-1) break;///若图不连通
else{
sum+=dist[k];
for(j=1;j<=n;j++)
if(mark[j]==0&&mapp[k][j]<dist[j])
dist[j]=mapp[k][j];
}
}
return sum;
}
int main() {
int m,a,b,y,i,j;
while(scanf("%d",&n)!=EOF){
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
scanf("%d",&mapp[i][j]);
scanf("%d",&m);///强已经建好的路权重归零
for(i=1;i<=m;i++){
scanf("%d %d",&a,&b);
mapp[a][b]=mapp[b][a]=0;
}
y=prim();
printf("%d\n",y);
}
return
hdu 1874
普莱姆算法
#include <iostream>
#include <queue>
#include <string.h>
#define Y 111100
#define N 1100
using namespace std;
int mapp[N][N],mark[N],dist[N],n,m,s,t;
void dijsta(int v0){
int i,j;
for(i=0;i<n;i++)
dist[i]=mapp[v0][i];
mark[v0]=1; dist[v0]=0;
for(i=1;i<n;i++){
int minn=Y,k=-1;
for(j=0;j<n;j++)
if(minn>dist[j]&&mark[j]==0)
{ minn=dist[j];
k=j;
}
mark[k]=1;
if(k!=-1){
for(j=0;j<n;j++)
if(mapp[k][j]<Y&&mark[j]==0){
if(dist[k]+mapp[k][j]<dist[j])
dist[j]=dist[k]+mapp[k][j];
}
}
}
}
int main()
{
int a,b,c,i,j,y=0;
while(cin>>n>>m){
memset(mark,0,sizeof(mark));
memset(dist,0,sizeof(dist));
for(i=0;i<n;i++){
for(j=0;j<n;j++){
mapp[i][j]=Y;
}
}
for(i=0;i<m;i++){
cin>>a>>b>>c;
if(mapp[a][b]>c)
mapp[a][b]=mapp[b][a]=c;
}
cin>>s>>t;
dijsta(s);
y=dist[t];
if(y==Y)
cout<<"-1"<<endl;
else
cout<<y<<endl;
}
return 0;
}
hdu 1875
普莱姆算法 prim
#include<stdio.h>
#include <string.h>
#include<stdlib.h>
#include <math.h>
#include <algorithm>
#define Y 111110000
using namespace std;
int mark[11000],n,left[11000],right[11000];
double mapp[11000][11000],dist[11000];
///注意类型
double prim(){
int i,j,k;
double sum=0.0,min;
for(i=0;i<n;i++)
dist[i]=mapp[0][i];
dist[0]=0,mark[0]=1;
for(i=1;i<n;i++){
min=1542487693.00,k=-1;
for(j=0;j<n;j++)
if(dist[j]<min&&mark[j]==0){
min=dist[j];
k=j;
}
mark[k]=1;
if(k==-1) break; ///若没找到满足条件的下标
else{
sum+=dist[k];
for(j=0;j<n;j++)
if(mark[j]==0&&mapp[k][j]<dist[j])
dist[j]=mapp[k][j];
}
}
return sum;
}
int main()
{
int T,i,j,k;
double ans=0.0,d;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
memset(mark,0,sizeof(mark));
for(i=0;i<n;i++)
scanf("%d %d",&left[i],&right[i]);
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(i!=j){
d=sqrt((left[i]-left[j])*(left[i]-left[j])+(right[i]-right[j])*(right[i]-right[j]));
if(d>=10&&d<=1000)
mapp[j][i]=mapp[i][j]=d;
else
mapp[j][i]=mapp[i][j]=Y;
}
ans=prim();
if(ans<Y)
printf("%.1lf\n",ans*100.0);
else
printf("oh!\n");
}
return 0;
}
克鲁斯卡算法 kruskal
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int m,per[500],cot;
struct node {
int x,y;
double dis;
}s[10000000];
double cmp(node x,node y)
{
return x.dis<y.dis;
}
int find(int x)
{
/*
int i=x,t=x,j;
while(t!=per[t])
t=per[t];
while(i!=t)
{
j=per[i];
per[i]=t;
i=j;
}
return t;
*/
if(x!=per[x])
per[x]=find(per[x]);
return per[x];
}
int main()
{
int N,n,a[300],b[300],i,j;
scanf("%d",&N);
while(N--)
{
cot=0;
scanf("%d",&m);
for(i=0;i<m;i++)
per[i]=i;
for(i=0;i<m;i++)
scanf("%d%d",&a[i],&b[i]);
int t=0;
for(i=0;i<m;i++)
{
for(j=0;j<i;j++)
{
s[t].x=i;
s[t].y=j;
double q=(sqrt((a[i]-a[j])*(a[i]-a[j])+(b[i]-b[j])*(b[i]-b[j])*1.0));
if(q<=1000&&q>=10)
s[t++].dis=q;
}
}
sort(s,s+t,cmp);
double sum=0;
int fx,fy;
for(i=0;i<t;i++)
{
fx=find(s[i].x),fy=find(s[i].y);
if(fx!=fy){
cot++;
per[fx]=fy;
sum+=s[i].dis;
}
}
if(cot!=m-1)
printf("oh!\n");
else
printf("%.1lf\n",sum*100);
}
return 0;
}
hdu 1879
普莱姆算法
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <string.h>
#define N 200
#define Y 900
using namespace std;
int n,m,dist[N],mapp[N][N],mark[N];
int Prime()
{
int sum=0,i,j;
for(i=1;i<=n;i++)
dist[i]=mapp[1][i];
mark[1]=1;dist[1]=0;
for(i=1;i<n;i++){
int minn=Y,k=-1;
for(j=1;j<=n;j++)
if(minn>dist[j]&&mark[j]==0)
{ minn=dist[j];
k=j;
}
mark[k]=1;
if(k!=-1){
sum+=dist[k];
for(j=1;j<=n;j++)
if(dist[j]>mapp[k][j]&&mark[j]==0)
dist[j]=mapp[k][j];
}
}
return sum;
}
int main()
{
int i,j;
int a,b,c,d;
while(scanf("%d",&n)!=EOF&&n){
m=n*(n-1)/2;memset(
mark,0,sizeof(mark));
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
mapp[i][j]=Y;
for(i=1;i<=m;i++){
scanf("%d %d %d %d",&a,&b,&c,&d);
if(d==0)
mapp[a][b]=mapp[b][a]=c;
else
mapp[a][b]=mapp[b][a]=0;
}
printf("%d\n",Prime());
}
return 0;
}
克鲁斯卡算法
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#define N 200
using namespace std;
struct node{
int a,b,c;
}mapp[N*N];
int fa[N];
int com(struct node t1,struct node t2){
return t1.c<t2.c;
}
int findfa(int x){
if(x!=fa[x])
fa[x]=findfa(fa[x]);
return fa[x];
}
int main()
{
int n,i,fx,fy,res,t;
while(scanf("%d",&n)&&n){
res=0;
for(i=1;i<=n;i++) fa[i]=i;
for(i=1;i<=n*(n-1)/2;i++){
scanf("%d %d %d %d",&mapp[i].a,&mapp[i].b,&mapp[i].c,&t);
if(t==1)
mapp[i].c=0;
}
sort(mapp+1,mapp+n*(n-1)/2+1,com);
for(i=1;i<=n*(n-1)/2;i++){
fx=findfa(mapp[i].a); fy=findfa(mapp[i].b);
if(fx!=fy){
fa[fx]=fy;
res+=mapp[i].c;
}
}
printf("%d\n",res);
}
return 0;
}
hdu 1301 前面感觉都是模板,这次来点不同的最小生成树,不同就在于n表示点的个数,而每个点的标号不在是数字而是大写字母,每行首个大写字母的后面的数字表示有几个点与行首大写字母相连,后面的数字表示两点之间的权重。求是图连通的最小生成树
克鲁斯卡算法
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#define N 100100
using namespace std;
struct node{
int a,b,c;
}mapp[N];
int fa[N];
int com(node t1,node t2){
return t1.c<t2.c;
}
int findfa(int x){
if(x!=fa[x])
fa[x]=findfa(fa[x]);
return fa[x];
}
int main(){
int n,m,i,j,p,q,fx,fy,res,l;
char c1,c2;
while(scanf("%d%*c",&n)!=EOF&&n){
m=n-1;
res=0;
l=0;
for(i=1;i<=n;i++) fa[i]=i;
for(i=1;i<=m;i++){
scanf("%c %d%*c",&c1,&p);
for(j=1;j<=p;j++){
scanf("%c %d%*c",&c2,&q);///%*c相当于getchar()
l++;
mapp[l].a=c1-'A'+1; mapp[l].b=c2-'A'+1; mapp[l].c=q;///把每个字母编号转换成数字编号
}
}
sort(mapp+1,mapp+l+1,com);
for(i=1;i<=l;i++){
fx=findfa(mapp[i].a); fy=findfa(mapp[i].b);
if(fx!=fy){
fa[fx]=fy;
res+=mapp[i].c;
--n;
}
}
printf("%d\n",res);
}
return 0;
}
hdu 1863
普莱姆算法
<pre name="code" class="html">#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#define N 200
#define Y 33333110
using namespace std;
int mapp[N][N],mark[N],dist[N],n,m,sum;
int prim(int v0){
memset(mark,0,sizeof(mark));
int i,j,minn,k,sum=0;
for(i=1;i<=n;i++)
dist[i]=mapp[v0][i];
mark[v0]=1; dist[v0]=0;
for(i=1;i<n;i++){
minn=Y;k=-1;
for(j=1;j<=n;j++)
if(mark[j]==0&&minn>dist[j]){
minn=dist[j];
k=j;
}
mark[k]=1;
if(k==-1){
return Y;
}
if(k!=-1){
sum+=dist[k];
for(j=1;j<=n;j++)
if(mark[j]==0&&mapp[k][j]<dist[j])
dist[j]=mapp[k][j];
}
}
return sum;
}
int main()
{
int i,j,a,b,c,y;
while(cin>>m&&m){
cin>>n;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
mapp[i][j]=Y;
for(i=1;i<=m;i++){
cin>>a>>b>>c;
if(mapp[a][b]>c)
mapp[a][b]=mapp[b][a]=c;
}
y=prim(1);
if(y==Y)
cout<<"?"<<endl;
else
cout<<y<<endl;
}
return 0;
}
克鲁斯卡算法
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#define N 200
#define Y 33333110
using namespace std;
struct node{
int a,b,c;
}mapp[N*6];
int fa[N*6];
int com(node t1,node t2){
return t1.c<t2.c;
}
int findfa(int x){
if(x!=fa[x])
fa[x]=findfa(fa[x]);
return fa[x];
}
int main()
{
int n,m,i,fx,fy,res;
while(cin>>m&&m){
cin>>n;
res=0;
for(i=1;i<=n;i++) fa[i]=i;
for(i=1;i<=m;i++)
cin>>mapp[i].a>>mapp[i].b>>mapp[i].c;
sort(mapp+1,mapp+m+1,com);
for(i=1;i<=m;i++){
fx=findfa(mapp[i].a); fy=findfa(mapp[i].b);
if(fx!=fy){
fa[fx]=fy;
res+=mapp[i].c;
--n;
}
}
if(n>1)
cout<<"?"<<endl;
else
cout<<res<<endl;
}
return 0;
}
我记得还有一道题,可是翻不到了,以后再来不吧