hdu 1874 畅通工程续

最短路径裸题 ,用了dijkstra , Floy  ,   Bellman-Floy   算法实现,纯粹练手

Dijkstra_数组模拟邻接表_优先队列STL实现 

 

#include <cstdio>

#include <cstring>

#include <queue>

#include <utility>

#define N 210

#define M 2020  //有1000条无向边,要转化为两条有向边保存

#define INF 0x3f3f3f3f

using namespace std;

typedef pair<int,int> pii;

struct edge

{int u,v,w,next;}e[M];

int first[N],d[N],done[N];

int n,m,s,t;



void input()

{

    memset(first,-1,sizeof(first));

    m*=2;  //m条无向边相当于2*m条有向边处理

    for(int i=0; i<m; i+=2)  //无向图,邻接表,每输入一边无向边相当于有两条有向边

    {

        int u;

        scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);

        e[i+1].u=e[i].v;  e[i+1].v=e[i].u; e[i+1].w=e[i].w;

        //先处理第一条有向边<u,v>,即e[i]里面的信息

        u=e[i].u;

        e[i].next=first[u];

        first[u]=i;

        //后处理第二条有向边<v,u>,即e[i+1]里面的信息

        u=e[i+1].u;

        e[i+1].next=first[u];

        first[u]=i+1;

    }

    scanf("%d%d",&s,&t);

/*

    printf("打印邻接表:\n");

    for(int i=0; i<n; i++)

    {

        printf("%d:",i);

        for(int k=first[i]; k!=-1; k=e[k].next)

        {

            int v=e[k].v , w=e[k].w;

            printf(" %d\\%d",v,w);

        }

        printf("\n");

    }

    printf("************************\n");

*/

    return ;

}

void dij_priority_queue()

{    

    priority_queue< pii,vector<pii>,greater<pii> > q;

    //优先队列需要三个参数,1.元素类型 2.容器类型 3.比较算子

    memset(d,0x3f,sizeof(d));     d[s]=0;

    memset(done,0,sizeof(done));

    q.push(make_pair(d[s],s));  //将一个二元组(d[s],s)放入优先队列



    while(!q.empty())

    {

        pii x;

        x=q.top();  q.pop();  //读入优先队列优先级最高的元素并且将其出队

        int u=x.second;     //得到二元组的第二个元素,也就是顶点的标号

        if(done[u])  continue;  //这个顶点已经算得最短路,直接抛弃

        done[u]=1;              //记得标记

        for(int k=first[u]; k!=-1; k=e[k].next)  //遍历u顶点的邻接表

        {

            int v=e[k].v , w=e[k].w ;

            if( d[u]+w < d[v] )   //可以松弛

            {

                d[v]=d[u]+w;

                q.push(make_pair(d[v],v));  //松弛成功的入队

            }

        }

    }



    if(d[t]==INF) printf("-1\n");

    else          printf("%d\n",d[t]);

    return ;

}

int main()

{

    while(scanf("%d%d",&n,&m)!=EOF)

    {

        input();

        dij_priority_queue();  //使用优先队列的dij求最短路

    }

    return 0;

}

 

 

 

Dijkstra算法_邻接矩阵

//dij算法,单源最短路径

//注意细节,可能有重边,取最小的那个

#include <stdio.h>

#include <string.h>

#define N 210

#define INF 1000000000

int S,V;

int n,m;

int g[N][N];

int cov[N],d[N];



void DIJ()

{

    int nn,min,k,i;

    

    d[S]=0;

    for(nn=1; nn<n; nn++)  //个数,还要求出源点S到其余所有点的最短路径

    {

        min=INF; k=S;

        for(i=0; i<n; i++)  //扫描所有的点

            if(!cov[i] && d[i]<min)

            {

                k=i;

                min=d[i];

            }

        cov[k]=1;



        for(i=0; i<n; i++)  //松弛操作

            if(!cov[i] && d[i] > min+g[k][i])

                d[i]=min+g[k][i];

    }

}

int main()

{

    int i,j,u,v,w;

    while(scanf("%d%d",&n,&m)!=EOF)

    {

        memset(cov,0,sizeof(cov));

        for(i=0; i<n; i++)

            for(d[i]=INF,j=0; j<n; j++)

                g[i][j]=INF;

        for(i=1; i<=m; i++)

        {

            scanf("%d%d%d",&u,&v,&w);

            if(g[u][v] > w) //判断重边

            g[u][v]=g[v][u]=w;

        }

        scanf("%d%d",&S,&V);

        DIJ();

        if(d[V]==INF) printf("-1\n");

        else          printf("%d\n",d[V]);

    }

    return 0;

}

 

 

Floy算法

#include <stdio.h>

#include <string.h>

#define N  210

#define INF 1000000000

int d[N][N];

int n,m,S,V;



void Floy()

{

    int i,j,k;



    for(k=0; k<n; k++)

        for(i=0; i<n; i++)

            for(j=0; j<n; j++)

                if(d[i][j] > d[i][k]+d[k][j])

                    d[i][j]=d[i][k]+d[k][j];

    return ;

}



int main()

{

    int i,j,u,v,w;

    while(scanf("%d%d",&n,&m)!=EOF)

    {

        for(i=0; i<n; i++)

            for(j=0; j<n; j++)

                if(i==j) d[i][j]=0;

                else     d[i][j]=INF;



        for(i=1; i<=m; i++)

        {

            scanf("%d%d%d",&u,&v,&w);

            if(w<d[u][v])

                d[u][v]=d[v][u]=w;

        }

        scanf("%d%d",&S,&V);

        Floy();

        if(d[S][V]==INF) printf("-1\n");

        else             printf("%d\n",d[S][V]);

/*

        for(i=0; i<n; i++)

        {

            for(j=0; j<n; j++)

                printf("%d ",d[i][j]);

            printf("\n");

        }

*/

     }

    return 0;

}

 

Bellman-Floy算法

#include <stdio.h>

#include <string.h>

#define N 210

#define INF 1000000000

int g[N][N],d[N];

int S,V,n,m;



void Bellman_Floy()

{

    int nn,i,j;

    d[S]=0;

    for(nn=1; nn<n; nn++) //定点数为n,要做n-1次

        //枚举所有的边i->j ,然后进行松弛操作

        for(i=0; i<n; i++)

            for(j=0; j<n; j++)

                if( d[j] > d[i]+g[i][j])

                    d[j]=d[i]+g[i][j];

}



int main()

{

    int i,j,u,v,w;

    while(scanf("%d%d",&n,&m)!=EOF)

    {

        for(i=0; i<n; i++)

            for(d[i]=INF,j=0; j<n; j++)

                g[i][j]=INF;



        for(i=1; i<=m; i++)

        {

            scanf("%d%d%d",&u,&v,&w);

            if(w<g[u][v])

                g[u][v]=g[v][u]=w;

        }

        scanf("%d%d",&S,&V);

        Bellman_Floy();

        if(d[V]==INF) printf("-1\n");

        else          printf("%d\n",d[V]);



    }

    return 0;

}

你可能感兴趣的:(HDU)