• ZOJ 3946 Highway Project


    SPFA 算法 + 小trick + 开longlong + 尽量别用结构体

    有一道题是酱紫的,单源最短路,给你一些路,给你这些路的长度,给你修这些路的话费,求最短路和最小花费。

    最短路很好求,就是用SPFA算法,值得注意的就是结构体很耗时,能不用就不用。

    1.SPFA算法:求单源最短路,先把0扔进去,看看有哪些边能够被松弛,把能被松弛的边松弛掉,然后把被松弛的点扔到队列里,直到没有点能被松弛。

    2.能用数组就别用结构体,不说了。。

    3.注意开longlong

    AC 代码:

    #include <string.h>
    #include <stdio.h>
    #define INF 0x3f3f3f3f
    #include <queue>
    #define N 50005 * 5
    using namespace std;
    
    int cnt,n,m;
    int head[N],vis[N];
    
    struct node
    {
        int v;
        int next;
        long long val;
        long long t;
    } edge[N];
    
    void add(int u,int v,int a,int b)
    {
        edge[cnt].t=a;
        edge[cnt].val=b;
        edge[cnt].v=v;
        edge[cnt].next=head[u];
        head[u]=cnt++;
    }
    
    long long  cost[N],tt[N];
    
    void SPFA()
    {
        memset(vis,0,sizeof(vis));
        memset(cost,INF,sizeof(cost));
        memset(tt,INF,sizeof(tt));
        queue<int>q;
        q.push(0);
        vis[0]=1;
        cost[0]=tt[0]=0;
        while (!q.empty())
        {
            int out = q.front();
            q.pop();
            vis[out] = 0;
            for (int i = head[out]; i + 1; i = edge[i].next)
            {
                if (tt[out] + edge[i].t <= tt[edge[i].v])
                {
                    if (tt[out] + edge[i].t < tt[edge[i].v])
                    {
                        tt[edge[i].v] = tt[out] + edge[i].t;
                        cost[edge[i].v] = edge[i].val;
                        if (!vis[edge[i].v])
                        {
                            q.push(edge[i].v);
                            vis[edge[i].v] = 1;
                        }
                    }
                    else if (cost[edge[i].v]>edge[i].val)  //时间相同考虑费用小的边
                    {
                        if (!vis[edge[i].v])
                        {
                            q.push(edge[i].v);
                            vis[edge[i].v] = 1;
                        }
                        cost[edge[i].v] = edge[i].val;
                    }
                }
            }
        }
    }
    int main()
    {
        int T,x,y,a,b;
        scanf("%d",&T);
        while(T--)
        {
            cnt=0;
            memset(head,-1,sizeof(head));
            scanf("%d%d",&n,&m);
            for(int i=0; i<m; i++)
            {
                scanf("%d%d%d%d",&x,&y,&a,&b);
                add(x,y,a,b);
                add(y,x,a,b);//前向星建图
            }
            SPFA();
            long long sum1=0,sum2=0;
            for (int i = 0; i < n; i++)
            {
                sum1 += tt[i];
                sum2 += cost[i];
            }
            printf("%lld %lld
    ", sum1, sum2);
        }
        return 0;
    }
  • 相关阅读:
    做了好几年的程序员,才发现自己天天都在用设计模式!
    先搞清楚这些问题,简历上再写你熟悉Java!
    Java中实现多线程继承Thread类与实现Runnable接口的区别
    JAVA中实现多线程的四种方式
    JDK和Cglib动态代理
    Java中选择排序,冒泡排序,插入排序,快速排序
    java死锁详解
    github常用命令
    字符串之StringBuffer 与 StringBuilder的对比
    基础数据类型之AbstractStringBuilder
  • 原文地址:https://www.cnblogs.com/qioalu/p/5435699.html
Copyright © 2020-2023  润新知