ZOJ3946 Highway Project(spfa,最短路变形)

描述

Edward, the emperor of the Marjar Empire, wants to build some
bidirectional highways so that he can reach other cities from the
capital as fast as possible. Thus, he proposed the highway project.

The Marjar Empire has N cities (including the capital), indexed from 0
to N - 1 (the capital is 0) and there are M highways can be built.
Building the i-th highway costs Ci dollars. It takes Di minutes to
travel between city Xi and Yi on the i-th highway.

Edward wants to find a construction plan with minimal total time
needed to reach other cities from the capital, i.e. the sum of minimal
time needed to travel from the capital to city i (1 ≤ i ≤ N). Among
all feasible plans, Edward wants to select the plan with minimal cost.
Please help him to finish this task.

Input

There are multiple test cases. The first line of input contains an
integer T indicating the number of test cases. For each test case:

The first contains two integers N, M (1 ≤ N, M ≤ 105).

Then followed by M lines, each line contains four integers Xi, Yi, Di,
Ci (0 ≤ Xi, Yi < N, 0 < Di, Ci < 105).

Output

For each test case, output two integers indicating the minimal total
time and the minimal cost for the highway project when the total time
is minimized.

Sample Input

2
4 5
0 3 1 1
0 1 1 1
0 2 10 10
2 1 1 1
2 3 1 2
4 5
0 3 1 1
0 1 1 1
0 2 10 10
2 1 2 1
2 3 1 2

Sample Output

4 3
4 4

思路

先说题意,题目给了n个点编号为(0~n-1)m条边,起点永远是0,对于每一条边有两个权值一个是通过这一条边的时间t,另一个是修路的花费c,现在这个人要从起点开始,走遍其他所有的点(每一次都是从起点开始然后到达其他点),问这个人从起点开始走的总时间是多少,在保证总时间最小的情况下,求花费最小。

对于第一问,我们可以直接求最短路,然后计算出从起点到每一点的最短路的总和就是答案,当计算花费的时候,我们计算出到达每一点的所有可能的在最短路上面的边,然后对于连接这些点的边找一个最小的,加起来总和就是答案。可以参考一下代码后面附的样例~

代码

#include <cstdio>
#include <cstring>
#include <cctype>
#include <stdlib.h>
#include <string>
#include <map>
#include <iostream>
#include <sstream>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
#include<list>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef long long ll;
const ll N=1e5+500;
const ll inf=1e18;
ll dis[N],vis[N],first[N],tot,n,m;
struct edge
{
    ll v,t,c,next;
} e[N*2];
void add_edge(ll u,ll v,ll t,ll c)
{
    e[tot].v=v,e[tot].t=t,e[tot].c=c;
    e[tot].next=first[u];
    first[u]=tot++;
}
void init()
{
    mem(first,-1);
    tot=0;
}
void spfa()
{
    for(ll i=1; i<=n; i++)
    {
        dis[i]=inf;
        vis[i]=0;
    }
    dis[1]=0;
    vis[1]=1;
    queue<ll>q;
    q.push(1);
    while(!q.empty())
    {
        ll u=q.front();
        q.pop();
        vis[u]=0;
        for(ll i=first[u]; ~i; i=e[i].next)
        {
            ll v=e[i].v,t=e[i].t;
            if(dis[u]+t<dis[v])
            {
                dis[v]=dis[u]+t;
                if(!vis[v])
                {
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
    ll ans1=0,ans2=0;//分别记录时间和花费
    for(ll i=1; i<=n; i++)
        ans1+=dis[i];
    vector<ll>g[N];
    q.push(1);
    while(!q.empty())
    {
        ll u=q.front();
        q.pop();
        for(ll i=first[u]; ~i; i=e[i].next)
        {
            ll c=e[i].c,v=e[i].v,t=e[i].t;
            if(dis[u]+t==dis[v])
            {
                g[v].push_back(c);
                q.push(v);
            }
        }
    }
    for(ll i=1; i<=n; i++)
    {
        ll minn=inf;
        for(ll j=0; j<g[i].size(); j++)
            minn=min(minn,g[i][j]);
        if(minn!=inf)
            ans2+=minn;
    }
    printf("%lld %lld\n",ans1,ans2);
}
int main()
{
    ll t,u,v,kase,c;
    scanf("%lld",&kase);
    while(kase--)
    {
        scanf("%lld%lld",&n,&m);
        init();
        for(ll i=1; i<=m; i++)
        {
            scanf("%lld%lld%lld%lld",&u,&v,&t,&c);
            u++,v++;
            add_edge(u,v,t,c);
            add_edge(v,u,t,c);
        }
        spfa();
    }
    return 0;
}

/*
1
4 4
0 1 1 1
1 2 1 1
0 2 2 2
0 3 1 2
*/

猜你喜欢

转载自blog.csdn.net/riba2534/article/details/80137893
今日推荐