图论常用模板

来源:互联网 发布:加拿大留学费用 知乎 编辑:程序博客网 时间:2024/05/18 02:51

自己将最短路和最小生成树的模板打了一遍,存一下。
最短路:
Floyd:

//给定n个点,m条边,输出(1,n)最短路,时间复杂度O(n*n*n)。#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;#define spot 100int a[spot+10][spot+10];const int inf=0x3f3f3f3f;int main(){    int n,m,i,j,k,x,y,z;    while(scanf("%d%d",&n,&m)!=EOF)    {        memset(a,0x3f,sizeof(a));        for(i=1; i<=n; i++)            a[i][i]=0;        for(i=1; i<=m; i++)            scanf("%d%d%d",&x,&y,&z),a[x][y]=min(z,a[x][y]),a[y][x]=a[x][y];        for(k=1; k<=n; k++)            for(i=1; i<=n; i++)                for(j=1; j<=n; j++)                    a[i][j]=min(a[i][j],a[i][k]+a[k][j]);      printf("%d\n",a[1][n]);    }    return 0;}

Dijkstra:

//迪杰斯特拉(无向图)给定n个点,m条遍,start起点,over终点,求(start,end)最短路,时间复杂度O(n*n)。#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;#define spot 1000int a[spot+10][spot+10],inf=0x3f3f3f3f,dis[spot+10],b[spot+10];int main(){    int n,m,start,over;    while(scanf("%d%d",&n,&m)!=EOF)  //n个点,m条遍    {        scanf("%d%d",&start,&over);  //给定起点start,终点over        memset(b,0,sizeof(b));        int i,j,x,y,z;        memset(a,0x3f,sizeof(a));        for(i=1; i<=n; i++)                a[i][i]=0;        for(i=1; i<=m; i++)            scanf("%d%d%d",&x,&y,&z),a[x][y]=min(a[x][y],z),a[y][x]=a[x][y];  //可能会有重遍        for(i=1; i<=n; i++)            dis[i]=a[start][i];        b[start]=1;        for(i=1; i<n; i++)        {            int minn=inf,u;            for(j=1; j<=n; j++)                if(dis[j]<minn&&!b[j])                    u=j,minn=dis[j];            b[u]=1;            for(j=1; j<=n; j++)                if(dis[j]>minn+a[u][j]&&a[u][j]<inf)                    dis[j]=minn+a[u][j];        }        printf("%d\n",dis[over]);    }}

bellman ford:

//贝尔曼 无向图 n个点,m条边,给定起点start,终点over,求(start,over)最短路,若无输出-1,,时间复杂度O(N*M)。#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;#define edge 10000 //边的条数int b[edge+10],dis[edge+10],inf=0x3f3f3f3f;struct stu{    int x,y,z;} c[edge+10];int main(){    int n,m;    while(scanf("%d%d",&n,&m)!=EOF)    {        int i,j,start,over;        scanf("%d%d",&start,&over);//起终点        for(i=1; i<=m; i++)            scanf("%d%d%d",&c[i].x,&c[i].y,&c[i].z); //边        memset(dis,0x3f,sizeof(dis));        dis[start]=0;        for(i=1; i<n; i++)            for(j=1; j<=m; j++)            {                dis[c[j].y]=min(dis[c[j].x]+c[j].z,dis[c[j].y]);                dis[c[j].x]=min(dis[c[j].y]+c[j].z,dis[c[j].x]);            }        printf("%d\n",dis[over]);    }    return 0;}

Spfa:

//无向图 贝尔曼的队列优化,给定n个点,m条边,起点start,终点over求(start,over)最短路#include<cstdio>#include<cstring>#include<queue>using namespace std;#define spot 100000 //点#define edge 1000000 //边struct stu{    int x,y,z;} a[2*edge+10];int dis[spot+10],first[spot+10],next1[2*edge+10],b[spot+10],inf=0x3f3f3f3f;int main(){    queue<int>q;    int n,m,start,over,i,j,xx,yy,zz,k;    while(scanf("%d%d%d%d",&n,&m,&start,&over)!=EOF)    {        j=0;        memset(dis,0x3f,sizeof(dis));        memset(first,-1,sizeof(first));        memset(b,0,sizeof(b));        dis[start]=0;        b[start]=1;        for(i=1; i<=m; i++)        {            scanf("%d%d%d",&xx,&yy,&zz);            a[++j].x=xx,a[j].y=yy,a[j].z=zz;            next1[j]=first[a[j].x];            first[a[j].x]=j;            a[++j].x=yy,a[j].y=xx,a[j].z=zz;            next1[j]=first[a[j].x];            first[a[j].x]=j;        }        q.push(start);        while(!q.empty())        {            k=q.front();            q.pop();            b[k]=0;            for(k=first[k]; k+1; k=next1[k])            {                if(dis[a[k].y]>dis[a[k].x]+a[k].z)                {                    dis[a[k].y]=dis[a[k].x]+a[k].z;                    if(!b[a[k].y])                        q.push(a[k].y),b[a[k].y]=1;                }            }        }        int maxx=inf;        printf("%d\n",dis[over]);    }    return 0;}

最小生成树:

Kruscal:

//Kruscal算法最小生成树 n个点,m条边,求最小长度#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;#define spot 100000   //点#define edge 1000000  //边struct stu{    int x,y,z;} a[edge+10];int b[spot+10];bool cmp(stu a,stu b){    return a.z<b.z;}int finds(int x){    int j,d=x;    while(x!=b[x])        x=b[x];    while(b[d]!=x)        j=d,d=b[d],b[j]=x;    return x;}bool mix(int x,int y){    int fx=finds(x),fy=finds(y);    if(fx!=fy)    {        b[fx]=fy;        return 0;    }    return 1;}int main(){    int n,m,i;    while(scanf("%d%d",&n,&m)!=EOF)    {        int sum=0,s=0;        for(i=1; i<=n; i++)            b[i]=i;        for(i=1; i<=m; i++)            scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);        sort(a+1,a+m+1,cmp);        for(i=1; i<=m; i++)        {            if(!mix(a[i].x,a[i].y))                sum++,s+=a[i].z;            if(sum==n-1)                break;        }        printf("%d\n",s);    }    return 0;}

Prim:

//矩阵输入的prim  有n*n的矩阵,求最小生成树#include<stdio.h>#include<string.h>#define spot 1000const int inf=0x3f3f3f3f;int a[spot+10][spot+10],dis[spot+10],b[spot+10];  //a[][]存矩阵,b[]标记,dis[]距离int main(){    int n;    while(scanf("%d",&n)!=EOF)    {        int sum=1,s=0,i,j;        for(i=1; i<=n; i++)            for(j=1; j<=n; j++)                scanf("%d",&a[i][j]);        memset(b,0,sizeof(b));        for(i=1; i<=n; i++)            dis[i]=a[1][i];        dis[1]=0;        b[1]=1;        while(sum<n)        {            int minn=inf,u;            for(i=1; i<=n; i++)                if(!b[i]&&minn>dis[i])                    minn=dis[i],u=i;            b[u]=1,sum++,s+=dis[u];            for(i=1; i<=n; i++)                if(!b[i]&&a[u][i]<dis[i])                    dis[i]=a[u][i];        }        printf("%d\n",s);    }    return 0;}
0 0
原创粉丝点击