[JZOJ5818] 【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联通就退出, 第一个答案求出。

然后加入所有边权小于第一个答案的边, 跑spfa求出S到T的最短路。

话说今天A组的题比B组简单多了。

 


 

 

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define int long long
inline int read() {
    int res=0;char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
    return res;
}
#define reg register 
#define N 500005
#define M 1000005
int n, m, S, T;
struct edge {
    int nxt, to, val, tim, from;
}ed[M*2], ed2[M*2];
int head[N], cnt;
inline void add(int x, int y, int z, int w)
{
    ed[++cnt] = (edge) {head[x], y, z, w, x};
    head[x] = cnt;
}
inline void ADD(int x, int y, int z, int w)
{
    ed2[++cnt] = (edge) {head[x], y, z, w, x};
    head[x] = cnt;
}
inline bool cmp(edge a, edge b)
{
    return a.val < b.val;
}
bool can[M*2];
int fa[N];
int Find(int x) {return x==fa[x]?x:fa[x]=Find(fa[x]);}
int ans;

int dis[N];
bool ex[N];
inline void spfa()
{
    memset(dis, 0x3f, sizeof dis);
    memset(ex, 0, sizeof ex);
    queue <int> q;
    q.push(S);
    dis[S] = 0;
    while(!q.empty())
    {
        int x = q.front();q.pop(); 
        ex[x] = 0;
        for (reg int i = head[x] ; i ; i = ed2[i].nxt)
        {
            int to = ed2[i].to;
            if (dis[to] > dis[x] + ed2[i].tim * ed2[i].val)
            {
                dis[to] = dis[x] + ed2[i].tim * ed2[i].val;
                if (!ex[to]) ex[to] = 1, q.push(to);
            }
        }
    } 
}

signed main()
{
    freopen("running.in", "r", stdin);
    freopen("running.out", "w", stdout);
    n = read(), m = read();
    for (reg int i = 1 ; i <= m ; i ++)
    {
        int x = read(), y = read(), z = read(), w = read();
        add(x, y, z, w);
    }
    S = read(), T = read();
    sort (ed + 1, ed + 1 + cnt, cmp);
    for (reg int i = 1 ; i <= n ; i ++) fa[i] = i;
    for (reg int i = 1 ; i <= cnt ; i ++)
    {
        int x = ed[i].from, y = ed[i].to;
        int fx = Find(x), fy = Find(y);
        if (fx == fy) continue;
        fa[fx] = fy;
        if (Find(S) == Find(T)) {ans = ed[i].val; break;}
    }
    int tot = cnt, cnt = 0;
    memset(head, 0, sizeof head);
    for (reg int i = 1 ; i <= tot ; i ++)
        if (ed[i].val <= ans) ADD(ed[i].from, ed[i].to, ed[i].val, ed[i].tim), ADD(ed[i].to, ed[i].from, ed[i].val, ed[i].tim);
    spfa();
    printf("%lld %lld\n", ans, dis[T]);
    return 0;
}

 

posted @ 2018-08-15 21:43  zZhBr  阅读(229)  评论(0编辑  收藏  举报