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;
}
原文地址:https://www.cnblogs.com/scau20110726/p/2755697.html