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