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\n", sum1, sum2);
    }
    return 0;
}

 

posted @ 2016-04-26 16:50  萌萌哒哒哒  阅读(225)  评论(0编辑  收藏  举报