最小生成树 (hdu)1102 1162 1233 1301 1863 7875 7873

来源:互联网 发布:软件著作权的有效期 编辑:程序博客网 时间:2024/05/19 13:15

大家都知道最小生成树有两种算法:prim(普利姆)———从点考虑,kruskal(克鲁斯卡)————从边考虑

初学最小生成树时,看的这篇博文,感觉棒棒哒点击打开链接

点击打开链接

hdu 1233 最小生成树#include <iostream>#include <algorithm>#include <stdio.h>#include <string.h>#define N 100100using 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 11100000using 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 1100using 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 111110000using 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 900using 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 200using 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 100100using 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 33333110using 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 33333110using 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;}
我记得还有一道题,可是翻不到了,以后再来不吧






0 0