2455:Secret Milking Machine
問題文
http://poj.org/problem?id=2455
1~Nの頂点があって、1からNの間をT回移動したい。
一度移動に使った辺は使用できない。
移動の時に使う辺のコストの最大値を最小化せよ。
二分探索+最大流。
二分探索で、移動に使用する辺の最大値を決め打ちする。
決めた値以下の辺のみでグラフを作る。容量は全て1。
このグラフで1からNへT以上流すことができたらその値で可能。
#include <iostream> #include <vector> #include <algorithm> #include <queue> #include <cstring> #include <cstdio> #define MAX_V 201 #define INF (1LL<<60) using namespace std; typedef long long ll; typedef pair<int,int> pii; struct edge{ll to,cap,rev;}; vector<edge> G[MAX_V]; void add_edge(ll from,ll to,ll cap){ G[from].push_back((edge){to,cap,G[to].size()}); G[to].push_back((edge){from,0,G[from].size()-1}); } ll level[MAX_V],iter[MAX_V]; ll bfs(ll s){ memset(level, -1, sizeof(level)); queue<ll>que; level[s]=0; que.push(s); while(!que.empty()){ ll v=que.front(); que.pop(); int sz=G[v].size(); for(int i=0;i<sz;i++){ edge &e=G[v][i]; if(e.cap>0 && level[e.to]<0){ level[e.to]=level[v]+1; que.push(e.to); } } } } ll dfs(ll v,ll t,ll f){ if(v==t)return f; int sz=G[v].size(); for(ll &i=iter[v];i<sz;i++){ edge &e=G[v][i]; if(e.cap>0 && level[v]<level[e.to]){ ll d=dfs(e.to,t,min(e.cap,f)); if(d>0){ e.cap-=d; G[e.to][e.rev].cap+=d; return d; } } } return 0; } ll max_flow(ll s,ll t){ ll flow=0; for(;;){ bfs(s); if(level[t]<0)return flow; memset(iter, 0, sizeof(iter)); ll f; while((f=dfs(s,t,INF))>0)flow+=f; } } int main(void){ ll n,p,t; cin >> n >> p >> t; ll from[p],to[p],cost[p],mx=0; for(int i=0;i<p;i++){ scanf("%lld %lld %lld",&from[i],&to[i],&cost[i]); from[i]--,to[i]--; mx=max(mx,cost[i]); } ll l=0,r=mx+1; while(r-l>1){ ll m=(l+r)/2; for(int i=0;i<n;i++)G[i].clear(); for(int i=0;i<p;i++){ if(cost[i]<=m){ add_edge(from[i],to[i],1LL); add_edge(to[i],from[i],1LL); } } if(max_flow(0,n-1)>=t)r=m; else l=m; } cout << r << endl; return 0; }