今天来水主题库里的有水分的紫题,随便一翻居然找到宝了。c++
小清新二分 + 网络流。git
考虑到题目中限制的是最大边权,要求最大边权最小,那么很容易想到二分答案。算法
单调性的证实:最大边权是对可行的边的一个限制,所以这个值越大,对可行的边的限制放的就越宽,可供选择的边就不会变少。凑齐 \(t\) 条边的机会不会变小。知足单调性。数组
考虑到要找到 \(t\) 条可行路径,能够抽象成为在全部边权的容量都为 \(1\) 的状况下,最大流不小于 \(t\)。网络
求解最大流这里我使用的 dinic 算法。优化
dinic 算法的时间复杂度为 \(\mathcal O(n^2m)\),实际上远远跑不满,并且它有各类虽然不影响渐进时间复杂度,可是可以大大提升实际运行效率的优化和剪枝。所以实际运行效率极高。spa
#include <bits/stdc++.h> namespace Basic { template <typename Temp> inline void read(Temp & res) { Temp fh = 1; res = 0; char ch = getchar(); for(; !isdigit(ch); ch = getchar()) if(ch == '-') fh = -1; for(; isdigit(ch); ch = getchar()) res = (res << 3) + (res << 1) + (ch ^ '0'); res = res * fh; } } using namespace Basic; using namespace std; const int Maxn = 2e2 + 5; const int Maxm = 8e4 + 5; int n, m, t, x, y, z; int l = 0, r = 0x7fffffff, mid, ans; struct e { int to, nxt, f; } b[Maxm]; int head[Maxn], ecnt; inline void add(int u, int v, int fl) {b[++ecnt] = (e) {v, head[u], fl}; head[u] = ecnt;} struct edg { int v_1, v_2, length; } b0[Maxm]; queue<int> q; int dep[Maxn], cur[Maxn]; bool bfs() { memset(dep, 0, sizeof(dep)); while(!q.empty()) q.pop(); q.push(1); dep[1] = 1; while(!q.empty()) { int tnow = q.front(); q.pop(); for(register int i = head[tnow]; i; i = b[i].nxt) { int tto = b[i].to, tf = b[i].f; if((dep[tto]) || (!tf)) continue; dep[tto] = dep[tnow] + 1; q.push(tto); if(tto == n) return true; } } return false; } int dfs(int t, int flow) { if(t == n) return flow; int rest = flow; for(; cur[t] && rest; cur[t] = b[cur[t]].nxt) { int tto = b[cur[t]].to, tf = b[cur[t]].f; if((dep[tto] != dep[t] + 1) || (!tf)) continue; int res = dfs(tto, min(tf, rest)); rest -= res; b[cur[t]].f -= res; b[cur[t] ^ 1].f += res; if(!res) dep[tto] = 0; if(!rest) return flow; } return flow - rest; } bool check(int lim) { int Maxflow = 0; memset(head, 0, sizeof(head)); ecnt = 1; for(register int i = 1; i <= m; ++i) { if(b0[i].length <= lim) { add(b0[i].v_1, b0[i].v_2, 1); add(b0[i].v_2, b0[i].v_1, 1); } } while(bfs()) { memcpy(cur, head, sizeof(cur)); Maxflow += dfs(1, 0x7fffffff >> 1); } return Maxflow >= t; } int main() { read(n); read(m); read(t); for(register int i = 1; i <= m; ++i) {read(b0[i].v_1); read(b0[i].v_2); read(b0[i].length);} while(l <= r) { int mid = (l + r) >> 1; if(check(mid)) ans = mid, r = mid - 1; else l = mid + 1; } printf("%d", ans); return 0; }