Secret Milking Machine
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 9658   Accepted: 2859

Description

Farmer John is constructing a new milking machine and wishes to keep it secret as long as possible. He has hidden in it deep within his farm and needs to be able to get to the machine without being detected. He must make a total of T (1 <= T <= 200) trips to
the machine during its construction. He has a secret tunnel that he uses only for the return trips. 



The farm comprises N (2 <= N <= 200) landmarks (numbered 1..N) connected by P (1 <= P <= 40,000) bidirectional trails (numbered 1..P) and with a positive length that does not exceed 1,000,000. Multiple trails might join a pair of landmarks. 



To minimize his chances of detection, FJ knows he cannot use any trail on the farm more than once and that he should try to use the shortest trails. 



Help FJ get from the barn (landmark 1) to the secret milking machine (landmark N) a total of T times. Find the minimum possible length of the longest single trail that he will have to use, subject to the constraint that he use no trail more than once. (Note
well: The goal is to minimize the length of the longest trail, not the sum of the trail lengths.) 



It is guaranteed that FJ can make all T trips without reusing a trail.

Input

* Line 1: Three space-separated integers: N, P, and T 



* Lines 2..P+1: Line i+1 contains three space-separated integers, A_i, B_i, and L_i, indicating that a trail connects landmark A_i to landmark B_i with length L_i.

Output

* Line 1: A single integer that is the minimum possible length of the longest segment of Farmer John's route.

Sample Input

7 9 2
1 2 2
2 3 5
3 7 5
1 4 1
4 3 1
4 5 7
5 7 1
1 6 3
6 7 3

Sample Output

5

Hint

Farmer John can travel trails 1 - 2 - 3 - 7 and 1 - 6 - 7. None of the trails travelled exceeds 5 units in length. It is impossible for Farmer John to travel from 1 to 7 twice without using at least one trail of length 5. 



Huge input data,scanf is recommended.

Source

题目大意:

FJ有N块地,这些地之间有P条双向路,每条路的都有固定的长度l。如今要你找出从第1块地到第n块地的T条不同路径,每条路径上的路不能与先前的路径反复,问这些路径中的最长路的最小是多少。

解题思路:

二分+网络流。

解题代码:

代码一:DINIC算法

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std; const int INF=(1<<30);
const int maxn=210,maxm=201000; struct edge{
int u,v,f,next;
edge(int u0=0,int v0=0,int f0=0){
u=u0;v=v0;f=f0;
}
}e[maxm]; int src,sink,cnt,head[maxn]; void adde(int u,int v,int f){
e[cnt].u=u,e[cnt].v=v,e[cnt].f=f,e[cnt].next=head[u],head[u]=cnt++;
e[cnt].u=v,e[cnt].v=u,e[cnt].f=0,e[cnt].next=head[v],head[v]=cnt++;
} void init(){
cnt=0;
memset(head,-1,sizeof(head));
} queue <int> q;
bool visited[maxn];
int dist[maxn]; void bfs(){
memset(dist,0,sizeof(dist));
while(!q.empty()) q.pop();
visited[src]=true;
q.push(src);
while(!q.empty()){
int s=q.front();
q.pop();
for(int i=head[s];i!=-1;i=e[i].next){
int d=e[i].v;
if(e[i].f>0 && !visited[d]){
q.push(d);
dist[d]=dist[s]+1;
visited[d]=true;
}
}
}
} int dfs(int u,int delta){
if(u==sink) return delta;
else{
int ret=0;
for(int i=head[u];delta && i!=-1;i=e[i].next){
if(e[i].f>0 && dist[e[i].v]==dist[u]+1){
int d=dfs(e[i].v,min(e[i].f,delta));
e[i].f-=d;
e[i^1].f+=d;
delta-=d;
ret+=d;
}
}
if(!ret) dist[u]=-2;
return ret;
}
} int maxflow(){
int ret=0;
while(true){
memset(visited,false,sizeof(visited));
bfs();
if(!visited[sink]) return ret;
ret+=dfs(src,INF);
}
return ret;
} int n,m,num,maxr,minr;
vector <edge> vec; void input(){
maxr=0;
minr=INF;
src=1,sink=n;
vec.clear();
int u,v,w;
for(int i=0;i<m;i++){
scanf("%d%d%d",&u,&v,&w);
vec.push_back(edge(u,v,w));
vec.push_back(edge(v,u,w));
if(w>maxr) maxr=w;
if(w<minr) minr=w;
}
} void build(int dis0){
init();
for(int i=0;i<vec.size();i++){
if(vec[i].f<=dis0){
adde(vec[i].u,vec[i].v,1);
}
}
} void solve(){
int l=minr,r=maxr;
while(l<r){
int mid=(l+r)/2;
build(mid);
if(maxflow()>=num) r=mid;
else l=mid+1;
}
printf("%d\n",r);
} int main(){
while(scanf("%d%d%d",&n,&m,&num)!=EOF){
input();
solve();
}
return 0;
}

代码二:sap算法

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std; #define INF 2000000000
#define N 100010
typedef long long ll; const int maxn=210;
struct edge{
int u,v,next,cap;
edge(int u0=0,int v0=0,int f0=0){
u=u0;v=v0;cap=f0;
}
}e[210000]; int n,head[N],tol,top,st[N];
int src,des,dep[N],gap[N]; void adde(int u,int v,int c){
e[tol].u=u,e[tol].v=v,e[tol].next=head[u],e[tol].cap=c,head[u]=tol++;
e[tol].u=v,e[tol].v=u,e[tol].next=head[v],e[tol].cap=0,head[v]=tol++;
} void bfs(){//对于反边计算层次
for(int i=0;i<N;i++) dep[i]=N-1;
memset(gap,0,sizeof gap);
gap[0]=1,dep[des]=0;
int q[N],l=0,r=0,u,v;
q[r++]=des;
while(l!=r){
u=q[l++];
l=l%N;
for(int i=head[u];i!=-1;i=e[i].next){
v=e[i].v;
if(e[i].cap!=0||dep[v]!=N-1) continue;
q[r++]=v;
r=r%N;
++gap[dep[v]=dep[u]+1];
}
}
} int sap(){
bfs();
int u=src,s[N],top=0,res=0,ii;
int cur[N];
memcpy(cur,head,sizeof head);
while(dep[src]<n){
if(u==des){//求得一条增广路
int minf=INF,pos=n;
for(int i=0;i<top;i++){
if(minf>e[s[i]].cap){
minf=e[s[i]].cap;
pos=i;
}
}
for(int i=0;i<top;i++){
e[s[i]].cap-=minf;
e[s[i]^1].cap+=minf;
}
top=pos;
res+=minf;
u=e[s[top]].u;//优化1
}
if(dep[u]!=0&&gap[dep[u]-1]==0) break;//出现断层
ii=-1;
for(int i=cur[u];i!=-1;i=e[i].next){
if(dep[e[i].v]==N-1) continue;
if(e[i].cap!=0&&dep[u]==dep[e[i].v]+1){ii=i;break;}
}
if(ii!=-1){//有同意弧
cur[u]=ii;
s[top++]=ii;
u=e[ii].v;
}else{//不断回退找增光路
int mind=n;
for(int i=head[u];i!=-1;i=e[i].next){
if(e[i].cap==0) continue;
if(dep[e[i].v]<mind) mind=dep[e[i].v],cur[u]=i;
}
--gap[dep[u]];
++gap[dep[u]=mind+1];//优化2
if(u!=src) u=e[s[--top]].u;
}
}
return res;
} int m,num,maxr,minr;
vector <edge> vec; void input(){
maxr=0;
minr=INF;
vec.clear();
int u,v,w;
for(int i=0;i<m;i++){
scanf("%d%d%d",&u,&v,&w);
vec.push_back(edge(u,v,w));
vec.push_back(edge(v,u,w));
if(w>maxr) maxr=w;
if(w<minr) minr=w;
}
} void build(int dis0){
tol=0;
memset(head,-1,sizeof head);
src=1,des=n,n;
int vsize=vec.size();
for(int i=0;i<vsize;i++){
if(vec[i].cap<=dis0) adde(vec[i].u,vec[i].v,1);
}
} void solve(){
int l=minr,r=maxr;
while(l<r){
int mid=(l+r)/2;
build(mid);
if(sap()>=num) r=mid;
else l=mid+1;
}
printf("%d\n",r);
} int main(){
while(scanf("%d%d%d",&n,&m,&num)!=EOF){
input();
solve();
}
return 0;
}

POJ 2455 Secret Milking Machine(搜索-二分,网络流-最大流)的更多相关文章

  1. POJ 2455 Secret Milking Machine 【二分】+【最大流】

    <题目链接> 题目大意: FJ有N块地,这些地之间有P条双向路,每条路的都有固定的长度l.现在要你找出从第1块地到第n块地的T条不同路径,每条路径上的路段不能与先前的路径重复,问这些路径中 ...

  2. POJ 2455 Secret Milking Machine(最大流+二分)

    Description Farmer John is constructing a new milking machine and wishes to keep it secret as long a ...

  3. POJ 2455 Secret Milking Machine (二分 + 最大流)

    题目大意: 给出一张无向图,找出T条从1..N的路径,互不重复,求走过的所有边中的最大值最小是多少. 算法讨论: 首先最大值最小就提醒我们用二分,每次二分一个最大值,然后重新构图,把那些边权符合要求的 ...

  4. poj 2455 Secret Milking Machine 二分+最大流 sap

    题目:p条路,连接n个节点,现在需要从节点1到节点n,不重复走过一条路且走t次,最小化这t次中连接两个节点最长的那条路的值. 分析:二分答案,对于<=二分的值的边建边,跑一次最大流即可. #in ...

  5. POJ 2455 Secret Milking Machine (二分+无向图最大流)

    [题意]n个点的一个无向图,在保证存在T条从1到n的不重复路径(任意一条边都不能重复)的前提下,要使得这t条路上经过的最长路径最短. 之所以把"经过的最长路径最短"划个重点是因为前 ...

  6. POJ 2455 - Secret Milking Machine

    原题地址:http://poj.org/problem?id=2455 题目大意:给出一个N个点的无向图,中间有P条边,要求找出从1到n的T条通路,满足它们之间没有公共边,并使得这些通路中经过的最长的 ...

  7. POJ2455 Secret Milking Machine【二分,最大流】

    题目大意:N个点P条边,令存在T条从1到N的路径,求路径上的边权的最大值最小为多少 思路:做了好多二分+最大流的题了,思路很好出 二分出最大边权后建图,跑dinic 问题是....这题是卡常数的好题! ...

  8. POJ 2455:Secret Milking Machine(二分+最大流)

    http://poj.org/problem?id=2455 题意:给出n个点和m条无向路,每条路都有一个长度.从1点到n点要走t次两两互不重合的路.求出每条1->n的路中相邻两点最大值的最小值 ...

  9. POJ 2455Secret Milking Machine(二分+网络流之最大流)

    题目地址:POJ2455 手残真浪费时间啊..又拖到了今天才找出了错误..每晚两道题不知不觉又变回了每晚一道题...sad.. 第一次在isap中忘记调用bfs,第二次则是遍历的时候竟然是从1開始遍历 ...

随机推荐

  1. Shader程序中内置的状态变量

    经常在着色器程序需要访问一些全局状态,像当前的 model view projection 矩阵,当前环境的颜色诸如此类. 内置的矩阵 UNITY_MATRIX_MVP:当前模型 视窗 投影矩阵 UN ...

  2. 根据checkBox或radio的勾选状态得到id数组

    $(function(){ var inputs = document.getElementsByTagName("input"); var realStrs = "&q ...

  3. [LeetCode]题解(python):071-Simplify Path

    题目来源: https://leetcode.com/problems/simplify-path/ 题意分析: 简化Unix上的绝对路径,也就是多个'/'代表一个,'..'表示返回上一级目录,‘.' ...

  4. MVC-05 Model(1)

    在开发应用程序的过程中,经常需要处理许多大大小小的数据,例如,SQL Server数据库存取.连接AD(Active Directory)数据库进行验证.调用外部Web Service取得数据等.除了 ...

  5. mybatis+postgresql平台

    mybatis+postgresql平台        最近有个项目的数据库使用postgresql,使用原生态的mybatis操作数据,原生态的没什么不好,只不过国内有个tk.mybatis的工具帮 ...

  6. 转: js中的getYear()函数的问题(推荐用 getFullYear())

    用了JS的getYear()方法,但是发现生成的代码竟然有108(本应该是2008),发现这是firefox下的问题. 然后google了一下,发 现原来是这样的:var today = new da ...

  7. WINDOWS操作系统中可以允许最大的线程数(线程栈预留1M空间)(56篇Windows博客值得一看)

    WINDOWS操作系统中可以允许最大的线程数 默认情况下,一个线程的栈要预留1M的内存空间 而一个进程中可用的内存空间只有2G,所以理论上一个进程中最多可以开2048个线程 但是内存当然不可能完全拿来 ...

  8. QT实现TCP通信服务器端和客户端(支持多个客户端)精简版

    上星期接了个私活,工期两星期,报酬3000,写一个小软件,采集定向网络上的数据,并进行双向通信,捣鼓了两天,终于把QT中tcp通信这块调通了,找过N多例子,绝大部分都是基本的一个服务端一个客户端通信的 ...

  9. C#共享内存类改进版

    原文 C#共享内存类改进版 改进说明及源码实例下载见:http://blog.csdn.net/zzh8845/archive/2008/11/22/3349963.aspx ShareMem.cs ...

  10. Libev学习笔记1

    和Libevent相似,Libev是一个高性事件驱动框架,据说性能比Libevent要高,bug比Libevent要少.Libev只是一个事件驱动框架,不是网络库,因为它的内部并没有任何socket编 ...