• 月球美容计划之最短路


    那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;
    }


    SPFA前向星版本号

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #define EGMAX 200000
    #define DOMAX 2000
    #define MAX 999999
    
    using namespace std;
    
    struct node
    {
        int e;
        int w;
        int next;
    }eg[EGMAX];
    
    int head[DOMAX];
    
    int cont;
    void add(int s,int e,int w)
    {
        eg[cont].e = e;
        eg[cont].w = w;
        eg[cont].next = head[s];
        head[s] = cont++;
    }
    
    int dis[DOMAX];
    bool vis[DOMAX];
    
    int SPFA(int s,int e,int n)
    {
    
        int now;
        queue<int> que;
        memset(vis,0,sizeof (vis));
        for (int i = 0;i <= n;i++)
            dis[i] = MAX;
    
        vis[s] = 1;
        dis[s] = 0;
        que.push(s);
    
        while (!que.empty())
        {
            now = que.front();
            que.pop();
            vis[now] = 0;
    
            for (int i = head[now];~i;i = eg[i].next)
            {
                if (dis[eg[i].e] > dis[now] + eg[i].w)
                {
                    dis[eg[i].e] = dis[now] + eg[i].w;
    
                    if (!vis[eg[i].e])
                    {
                        vis[eg[i].e] = 1;
                        que.push(eg[i].e);
                    }
                }
            }
        }
    
        return dis[e];
    
    }
    
    int main()
    {
        int n,m;
        
        while (~scanf ("%d%d",&n,&m) && (n || m))
        {
            cont = 0;
            memset(head,-1,sizeof (head));
            for(int i = 0;i < m;i++)
            {
                int s,e,w;
                scanf ("%d%d%d",&s,&e,&w);
                add(s,e,w);
                add(e,s,w);
            }
    
            int ans = SPFA(1,n,n);
    
            printf ("%d
    ",ans);
        }
        return 0;
    }
    


    http://blog.csdn.net/codehypo

  • 相关阅读:
    [BJOI2016] 回转寿司
    [洛谷P4115] Qtree4 & [ZJOI2007] 捉迷藏
    [POI2011] METMeteors
    [NOI2020] 命运
    [20220404联考] 条条下水道通祖安
    相机丢图解决方案
    网卡一些设置,摘自百度文库
    设置 Qtabwidget 窗体透明
    DevExpress RibbonControl菜单组底部怎么去掉 学无止境
    Python篇:某宝毫秒级的精准秒杀
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4510184.html
Copyright © 2020-2023  润新知