diff --git a/P1967.cpp b/P1967.cpp new file mode 100644 index 0000000..7a579bc --- /dev/null +++ b/P1967.cpp @@ -0,0 +1,128 @@ +#include +using namespace std; +int n, m, q; +int a[10005]; +vector>> edge; +vector> fri[10005]; +struct BCJ { + int fa[10005]; + int find(int x) { + if (fa[x] == x) return x; + return fa[x] = find(fa[x]); + } +} b; +struct SEG { + int num[10005 * 4]; + void init(int now, int nl, int nr) { + if (nl == nr) { + num[now] = a[nl]; + return; + } + int mid = (nl + nr) >> 1; + init(now * 2, nl, mid); + init(now * 2 + 1, mid + 1, nr); + num[now] = min(num[now * 2], num[now * 2 + 1]); + } + int query(int now, int nl, int nr, int l, int r) { + if (nr < l || nl > r) return INT_MAX; + if (l <= nl && nr <= r) return num[now]; + int mid = (nl + nr) >> 1; + return min(query(now * 2, nl, mid, l, r), query(now * 2 + 1, mid + 1, nr, l, r)); + } +} seg; +int fa[10005]; +pair son[10005]; +int cnt[10005]; +int top[10005]; +int dfn[10005]; +int dep[10005]; +int nowdfn; +void dfs1(int now, int from) { + cnt[now] = 1; + for (auto i : fri[now]) { + int v = i.second; + int w = i.first; + if (v == from) continue; + fa[v] = now; + dep[v] = dep[now] + 1; + dfs1(v, now); + cnt[now] += cnt[v]; + if (cnt[son[now].first] < cnt[v]) { + son[now].first = v; + son[now].second = w; + } + } +} +void dfs2(int now, int from, int w) { + dfn[now] = ++nowdfn; + top[now] = from; + a[dfn[now]] = w; + if (son[now].first) { + dfs2(son[now].first, from, son[now].second); + } + for (auto i : fri[now]) { + int v = i.second; + int ww = i.first; + if (v == fa[now] || v == son[now].first) continue; + dfs2(v, v, ww); + } +} +int pt(int x, int y) { + if (x == y) return INT_MAX; + int ans = INT_MAX; + while (top[x] != top[y]) { + if (dep[top[x]] < dep[top[y]]) swap(x, y); + ans = min(ans, seg.query(1, 1, n, dfn[top[x]], dfn[x])); + x = fa[top[x]]; + } + if (dep[x] < dep[y]) swap(x, y); + if (dfn[y] + 1 <= dfn[x]) { + ans = min(ans, seg.query(1, 1, n, dfn[y] + 1, dfn[x])); + } + return ans; +} +int main() { + scanf("%d%d", &n, &m); + for (int i = 1; i <= n; ++i) { + b.fa[i] = i; + } + for (int i = 1, u, v, w; i <= m; ++i) { + scanf("%d%d%d", &u, &v, &w); + edge.push_back({w, {u, v}}); + } + sort(edge.begin(), edge.end(), + [](const pair> &x, + const pair> &y) { + return x.first > y.first; + }); + for (auto i : edge) { + int w = i.first; + int u = i.second.first; + int v = i.second.second; + if (b.find(u) != b.find(v)) { + fri[u].push_back({w, v}); + fri[v].push_back({w, u}); + b.fa[b.find(u)] = b.find(v); + } + } + for (int i = 1; i <= n; ++i) { + if (!dfn[i]) { + dfs1(i, 0); + dfs2(i, i, INT_MAX); + } + } + seg.init(1, 1, n); + scanf("%d", &q); + while (q--) { + int x, y; + scanf("%d%d", &x, &y); + if (b.find(x) != b.find(y)) { + printf("-1\n"); + continue; + } + int ans = pt(x, y); + printf("%d\n", ans == INT_MAX ? -1 : ans); + } + + return 0; +} \ No newline at end of file diff --git a/P1967.md b/P1967.md new file mode 100644 index 0000000..3292b8d --- /dev/null +++ b/P1967.md @@ -0,0 +1,58 @@ +# P1967 [NOIP 2013 提高组] 货车运输 + +## 题目背景 + +NOIP2013 提高组 D1T3 + +## 题目描述 + +A 国有 $n$ 座城市,编号从 $1$ 到 $n$,城市之间有 $m$ 条双向道路。每一条道路对车辆都有重量限制,简称限重。 + +现在有 $q$ 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。 + +## 输入格式 + +第一行有两个用一个空格隔开的整数 $n,m$,表示 A 国有 $n$ 座城市和 $m$ 条道路。 + +接下来 $m$ 行每行三个整数 $x, y, z$,每两个整数之间用一个空格隔开,表示从 $x$ 号城市到 $y$ 号城市有一条限重为 $z$ 的道路。 +注意:$x \neq y$,两座城市之间可能有多条道路。 + +接下来一行有一个整数 $q$,表示有 $q$ 辆货车需要运货。 + +接下来 $q$ 行,每行两个整数 $x,y$,之间用一个空格隔开,表示一辆货车需要从 $x$ 城市运输货物到 $y$ 城市,保证 $x \neq y$。 + +## 输出格式 + +共有 $q$ 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。 +如果货车不能到达目的地,输出 $-1$。 + +## 输入输出样例 #1 + +### 输入 #1 + +``` +4 3 +1 2 4 +2 3 3 +3 1 1 +3 +1 3 +1 4 +1 3 +``` + +### 输出 #1 + +``` +3 +-1 +3 +``` + +## 说明/提示 + +对于 $30\%$ 的数据,$1 \le n < 1000$,$1 \le m < 10,000$,$1\le q< 1000$; + +对于 $60\%$ 的数据,$1 \le n < 1000$,$1 \le m < 5\times 10^4$,$1 \le q< 1000$; + +对于 $100\%$ 的数据,$1 \le n < 10^4$,$1 \le m < 5\times 10^4$,$1 \le q< 3\times 10^4 $,$0 \le z \le 10^5$。 \ No newline at end of file