《1625: Secret Milking Machine》
一开始一直想着最短路松弛,但是发现这样很难处理T条长度排序的边。
正解:二分最大限制边,然后最大流去check。
对于边 <= 最大限制边的就可以连接两点,容量为1。
然后最后汇点和源点连1,n,容量为INF。
最后判断最大值是否大于二分值即可。
细节:边数组要开4倍,因为无向图加反向边。
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> pii; const int N = 205; const int M = 4e4+5; const LL Mod = 1e9+7; #define pi acos(-1) #define INF 1e9 #define CT0 cin.tie(0),cout.tie(0) #define IO ios::sync_with_stdio(false) #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline LL read(){ LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } } using namespace FASTIO; int n,p,T,tot = -1,head[N],dep[N],cur[N],s,t; struct Input{int st,to,dis;}mm[M]; struct Node{int to,dis,next;}e[M << 2]; inline void add(int u,int v,int w) { e[++tot].to = v,e[tot].dis = w,e[tot].next = head[u],head[u] = tot; e[++tot].to = u,e[tot].dis = 0,e[tot].next = head[v],head[v] = tot; } bool bfs()//分层 { queue<int> Q; memset(dep,-1,sizeof(dep)); dep[s] = 0; Q.push(s); while(!Q.empty()) { int u = Q.front(); Q.pop(); for(int i=head[u];i!=-1;i=e[i].next) { int y = e[i].to,d = e[i].dis; if(dep[y] == -1 && d > 0) { dep[y] = dep[u]+1; Q.push(y); } } } return dep[t] != -1; } int dfs(int u,int flow) { int nowflow = 0,k; if(u == t) return flow; for(int i=head[u];i!=-1;i=e[i].next) { cur[u] = i;//当前弧优化 int y = e[i].to,d = e[i].dis; if((dep[y] == dep[u]+1) && d > 0) { if(k = dfs(y,min(flow-nowflow,d))) { e[i].dis -= k; e[i^1].dis += k; nowflow += k; if(nowflow == flow) break; } } } if(nowflow == 0) dep[u] = -1;//炸点优化 return nowflow; } LL solve() { LL ans = 0; while(bfs()) { for(int i = 1;i <= n;++i) cur[i] = head[i]; ans += dfs(s,INF); } return ans; } bool check(int x) { tot = -1,s = 0,t = n + 1; for(int i = 0;i <= n + 1;++i) head[i] = -1; for(int i = 1;i <= p;++i) { if(mm[i].dis <= x) add(mm[i].st,mm[i].to,1),add(mm[i].to,mm[i].st,1); } add(s,1,INF),add(n,t,INF); LL ans = solve(); if(ans >= T) return true; return false; } int main() { n = read(),p = read(),T = read(); int mx = 0; for(int i = 1;i <= p;++i) mm[i].st = read(),mm[i].to = read(),mm[i].dis = read(),mx = max(mx,mm[i].dis); int L = 0,r = mx,ans = 0; while(L <= r) { int mid = (L + r) >> 1; if(check(mid)) r = mid - 1,ans = mid; else L = mid + 1; } printf("%d\n",ans); system("pause"); return 0; }