JZOJ 5818. 【NOIP提高A组模拟2018.8.15】 做运动

Description

一天,Y 君在测量体重的时候惊讶的发现,由于常年坐在电脑前认真学习,她的体重有了突 飞猛进的增长。
幸好 Y 君现在退役了,她有大量的时间来做运动,她决定每天从教学楼跑到食堂来减肥。
Y 君将学校中的所有地点编号为 1 到 n,其中她的教学楼被编号为 S,她的食堂被编号为 T, 学校中有 m 条连接两个点的双向道路,保证从任意一个点可以通过道路到达学校中的所有点。
然而 Y 君不得不面临一个严峻的问题,就是天气十分炎热,如果 Y 君太热了,她就会中暑。 于是 Y 君调查了学校中每条路的温度 t,及通过一条路所需的时间 c。Y 君在温度为 t 的地 方跑单位时间,就会使她的热量增加 t。
由于热量过高 Y 君就会中暑,而且 Y 君也希望在温度较低的路上跑,她希望在经过的所有 道路中最高温度最低的前提下,使她到达食堂时的热量最低 (从教学楼出发时,Y 君的热量为 0)。
请你帮助 Y 君设计从教学楼到食堂的路线,以满足她的要求。你只需输出你设计的路线中所 有道路的最高温度和 Y 君到达食堂时的热量。
 

Input

第一行由一个空格隔开的两个正整数 n, m,代表学校中的地点数和道路数。
接下来 m 行,每行由一个空格隔开的四个整数 a, b, t, c 分别代表双向道路的两个端点,温度 和通过所需时间.
最后一行由一个空格隔开的两个正整数 S, T,代表教学楼和食堂的编号。
注意:输入数据量巨大,请使用快速的读入方式。

Output

一行由一个空格隔开的两个整数,分别代表最高温度和热量。 
 

Sample Input

5 6
1 2 1 2
2 3 2 2
3 4 3 4
4 5 3 5
1 3 4 1
3 5 3 6
1 5

Sample Output

3 24
 

Data Constraint

10% 的数据满足 t = 0
另外 10% 的数据满足 c = 0
另外 30% 的数据满足 n ≤ 2000
100% 的数据满足 n ≤ 5 × 10^5 , m ≤ 10^6 , 0 ≤ t ≤ 10000, 0 ≤ c ≤ 10^8 , 1 ≤ a, b, S, T ≤ n, S ≠ T
 
做法:将边按温度从小到大排序,用并查集加边查询S和T的联通情况,当S和T恰好联通时(剩下的温度相同的也要加进去),跑一遍spfa就可以了
代码如下:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#define N 1000007
#define NU 17442269567978
#define LL long long
using namespace std;
LL n, m, S, T, tot, ls[N], Ans, cnt;
LL dis[N];
int f[N];
struct edge
{
    LL to, next;
    LL w;    
}e[N * 2];
struct arr
{
    int x, y, t, w;
}E[N];
queue<LL> q;
bool v[N * 2];

inline int Read()
{
    int s = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9')    ch = getchar();
    while (ch >= '0' && ch <= '9')    s = s * 10  + ch - '0', ch = getchar();
    return s;
}

inline void Add(int x, int y, LL z)
{
    e[++tot].to = y;
    e[tot].w = z;
    e[tot].next = ls[x];
    ls[x] = tot;
}

int Find(int x)
{
    if (f[x] == 0)    return x;
    f[x] = Find(f[x]);
    return f[x];
}

void Work()
{
    for (int i = 1; i <= m; i++)
    {
        int u = Find(E[i].x), v = Find(E[i].y);
        if (u != v)    f[u] = v;
        if (Find(S) == Find(T))
        {
            cnt = i;
            int k = E[i].t;
            for (int j = i + 1; j <= m; j++)
            {
                if (E[j].t > k)    break;
                cnt = j;
            }
            Ans = k;
            return;
        }
    }
}

void Spfa()
{
    for (int i = 1; i <= n; i++)
        dis[i] = NU;
    memset(v, 0, sizeof(v));
    dis[S] = 0;
    v[S] = 1;
    q.push(S);
    for (; !q.empty();)
    {
        int now = q.front();
        q.pop();
        for (int i = ls[now]; i; i = e[i].next)
        {
            if (dis[now] + e[i].w < dis[e[i].to])
            {
                dis[e[i].to] = dis[now] + e[i].w;
                if (!v[e[i].to])
                {
                    v[e[i].to] = 1;
                    q.push(e[i].to);
                }
            }
        }
        v[now] = 0;
    }
}

int Cmp(arr x, arr y)
{
    return x.t < y.t;
}

void Init()
{
    for (int i = 1; i <= cnt; i++)
    {
        Add(E[i].x, E[i].y, (LL)(E[i].t * E[i].w));
        Add(E[i].y, E[i].x, (LL)(E[i].t * E[i].w));
    }
}

int main()
{
    freopen("running.in", "r", stdin);
    freopen("running.out", "w", stdout);
    n = Read(), m = Read();
    for (int i = 1; i <= m; i++)
        E[i].x = Read(), E[i].y = Read(), E[i].t = Read(), E[i].w = Read();
    sort(E + 1, E + m + 1, Cmp);
    S = Read();
    T = Read();
    Work();
    Init();
    Spfa();
    printf("%d", Ans);
    printf(" %lld", dis[T]);
}
原文地址:https://www.cnblogs.com/traveller-ly/p/9485091.html