• 月球美容计划之最短路


    那HDU的2544作为复习最短路的题目,用不同算法。

    迪杰斯特拉

    有点像普利姆算法的精简版,不能有负权边

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define MAX 99999
    #define qmin(a,b) a > b ? b : a
    
    //最短路
    //迪杰斯特拉
    
    int G[200][200];
    int vis[200];
    
    int djs (int n,int s)
    {
        int d[200];
        memset(vis,0,sizeof(vis));
        int i,k;
        for (i = 1;i <= n;i++)
            d[i] = G[1][i];
        d[1] = 0;
        vis[1] = 1;
    
        int imin,xb = 1;
        for (i = 1;i < n;i++)
        {
            imin = MAX;
            for (k = 1;k <= n;k++)						//以xb为起点↓
                if (!vis[k] && d[xb] + G[xb][k] < d[k])  //最短的那条边,快到碗里来
                    d[k] = d[xb] + G[xb][k];
    
            vis[xb] = 1;
    
            for (k = 1;k <= n;k++)
                if (!vis[k] && imin > d[k])
                    imin = d[xb = k];           //找到最小的点,并以此为起点找最短
            vis[xb] = 1;
        }
        return d[n];
    }
    
    int main()
    {
        int n,m;
    
        while (scanf ("%d%d",&n,&m),n || m)
        {
            int i,k;
    
            for (i = 0;i <= n;i++)
                for (k = 0;k <= n;k++)
                    if (i == k)
                        G[i][k] = 0;
                    else
                        G[i][k] = MAX;
    
            for (i = 0;i < m;i++)
            {
                int a,b,c;
                scanf ("%d%d%d",&a,&b,&c);
                if (c < G[a][b])
                {
                    G[a][b] = c;
                    G[b][a] = c;
                }
            }
    
            int ans = djs(n,1);
    
            printf ("%d
    ",ans);
        }
        return 0;
    }

    贝尔曼福特

    能够有负权边,就是不停的松弛,时间复杂度有点高

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define MAX 99999
    #define qmin(a,b) a > b ? b : a
    
    //最短路
    //贝尔曼福特
    
    struct E
    {
        int e,v;
        int w;
    }e[10000];
    
    int cont;
    
    int BF (int n,int s)
    {
        int d[200];
        int i,k;
        for (i = 0;i <= n;i++)
            d[i] = MAX;
    
        d[s] = 0;
    
        for (i = 1;i < n;i++)     //找n - 1条边
        {
            for (k = 0;k < cont;k++)  //把每条边都遍历一遍
            {
                int a = e[k].e,b = e[k].v;
                d[b] = qmin (d[b],d[a] + e[k].w);  //松弛
            }
        }
    
        return d[n];
    }
    
    int main()
    {
        int n,m;
    
        while (scanf ("%d%d",&n,&m),n || m)
        {
            int i,k;
    
            cont = 0;
            for (i = 0;i < m;i++)
            {
                int a,b,c;
                int tf = 1;
                scanf ("%d%d%d",&a,&b,&c);
    
                for (k = 0;k < cont;k++)
                    if ((e[k].e == a && e[k].v == b) || (e[k].e == b && e[k].v == a))
                        if (e[k].w > c)
                        {
                            e[k].w = c;
                            tf = 0;
                            break;
                        }
    
                if (tf)
                {
    				//无向图
                    e[cont].e = a;
                    e[cont].v = b;
                    e[cont++].w = c;
                    e[cont].e = b;
                    e[cont].v = a;
                    e[cont++].w=c;
                }
            }
    
            int ans = BF(n,1);
    
            printf ("%d
    ",ans);
        }
        return 0;
    }


     

    弗洛伊德

    这简直就像暴力啊,时间复杂度大的夸张,可是求出了每两个点之间的最短路,对于数据多并且图小的题目还是能够考虑的。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define MAX 99999
    #define qmin(a,b) a > b ? b : a
    
    //最短路
    //弗洛伊德
    
    int G[200][200];
    
    int fld (int n,int s)
    {
        int d[200][200];
        int i,j,k;
        memcpy(d,G,sizeof (G));
    
        for (i = 0;i <= n;i++)
            for (k = 0;k <= n;k++)
                for (j = 0;j <= n;j++)
                    d[k][j] = qmin (d[k][j],d[k][i] + d[i][j]);
    
        return d[s][n];
    }
    
    int main()
    {
        int n,m;
    
        while (scanf ("%d%d",&n,&m),n || m)
        {
            int i,k;
    
            //邻接矩阵初始化
    
            for (i = 0;i <= n;i++)
                for (k = 0;k <= n;k++)
                    if (i == k)
                        G[i][k] = 0;
                    else
                        G[i][k] = MAX;
    
            for (i = 0;i < m;i++)
            {
                int a,b,c;
                scanf ("%d%d%d",&a,&b,&c);
    
                if (G[a][b] > c)
                {
                    G[a][b] = c;
                    G[b][a] = c;
                }
            }
    
            int ans = fld(n,1);
    
            printf ("%d
    ",ans);
        }
        return 0;
    }


     

    SPFA

    BF的队列优化,有点像BFS。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define MAX 99999
    #define qmin(a,b) a > b ? b : a
    
    //最短路
    //SPFA
    
    struct node
    {
        int v;
        int w;
        struct node *next;
    }head[10001];
    
    int q[1000000];   //队列
    int s = 0,e = 0;
    int SPFA (int n,int st)
    {
        bool inq[200];  //标记是否还在队列中(队列中的不在入队列)
        int d[200];
        int i;
    
        memset (inq,0,sizeof (inq));
        for (i = 0;i <= n;i++)
            d[i] = MAX;
        s = 0;
        e = 0;
        d[st] = 0;
        q[s++] = st;
        inq[st] = 1;    //源点入队列并标记
        while (s > e)
        {
            int now = q[e++];
            inq[now] = 0;  //出队列的就恢复标记
    
            struct node *p = head[now].next;
    
            while (p != NULL)
            {
                if(d[p->v] > d[now] + p->w)  //松弛成功
                {
                    d[p->v] = d[now] + p->w;
    
                    if (!inq[p->v])         //假设在队列中就不入队列
                    {
                        q[s++] = p->v;
                        inq[p->v] = 1;
                    }
                }
                p = p->next;
            }
        }
        return d[n];          //其它的和BF一样了
    }
    
    int add (int a,int b,int c)    //邻接链表
    {
        struct node *t = new node;
        t->v = b;
        t->w = c;
        t->next = NULL;
    
        struct node *p = &head[a];
    
        while (p->next != NULL)
            p = p->next;
    
        p->next = t;
    
        return 1;
    }
    
    int main()
    {
        int n,m;
    
        while (scanf ("%d%d",&n,&m),n || m)
        {
            memset(head,0,sizeof (head));
            int i,k;
    
            for (i = 0;i < m;i++)
            {
                int a,b,c;
                int tf = 1;
                scanf ("%d%d%d",&a,&b,&c);
    
                add (a,b,c);
                add (b,a,c);
            }
    
            int ans = SPFA(n,1);
    
            printf ("%d
    ",ans);
        }
        return 0;
    }


    http://blog.csdn.net/codehypo

  • 相关阅读:
    打印杨辉三角
    插值排序
    各种冒泡排序法
    Linux系统命令符01
    2.1博客系统 |基于form组件和Ajax实现注册登录
    python面试笔试题,你都会了吗?快来复习
    1.2博客系统 |登录页| 验证码
    1.1博客系统| 表结构
    第五章:5.2面向对象-绑定方法和非绑定方法| 内置方法 |元类
    11.Django|中间件
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/3816389.html
Copyright © 2020-2023  润新知