[JZOJ5818] 【NOIP提高A组模拟2018.8.15】 做运动
把边权从小到大排序, 然后一个个加入,用并查集维护连通性, 如果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; }