今天來水主題庫裏的有水分的紫題,隨便一翻居然找到寶了。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; }