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. 在C语言中基本数据类型所占的字节数

    基本数据类型所占的字节数其实跟C语言本身没有太大的关系,它取决于编译器的位数,下面这张表说明了不同编译器下基本数据类型的长度: 32位编译器中各基本类型所占字节数: 注:对于32位的编译器,指针变量的 ...

  2. centos6.5安装vsftpd

    开通FTP有gssftp和vsftpd二种,查了查,据说vsftpd更稳定和更安全.就用vsftpd吧. 什么是vsftpd vsftpd是一款在Linux发行版中最受推崇的FTP服务器程序.特点是小 ...

  3. 托管服务帐号(Managed Service Account)

    托管服务帐号是绑定到单独的机器上,并且仅用于服务所用,所以不能用来登录. 创建托管帐号,不需要指定密码,密码会由活动目录自动管理.并且根据密码策略(默认30天)自动刷新,期间不影响服务. 在创建完之后 ...

  4. winform代码:关联窗体数据更新,删除dataGridview中选中的一行或多行

    一.关联窗体数据更新 关联窗体数据修改时,如果一个为总体数据显示窗体A,另一个为详细修改窗体B,从A进入B,在B中对数据进行修改,然后返回A,这时A窗体的数据需要更新. 我采用最简单的方法,首先保证每 ...

  5. setTimeout 虚假的“异步”

    看这篇http://www.laruence.com/2009/09/23/1089.html 所以实际上 setTimeout更像是任务按照队列执行  经过setTimeout设置后任务放在了队尾 ...

  6. 启用Apache Mod_rewrite模块

    Ubuntu 环境 在终端中执行 sudo a2enmod rewrite 指令后,即启用了 Mod_rewrite 模块. 另外,也可以通过将 /etc/apache2/mods-available ...

  7. mac 下安装和卸载 mysql

    这里有一篇文章写得很详细: http://www.cnblogs.com/macro-cheng/archive/2011/10/25/mysql-001.html 关于卸载,我也百度了下.找了好几个 ...

  8. java学习之JDBC

    之前学习了数据库原理,上学期也学了oracle数据库,我的学习视频上是讲的mysql数据库,其实都差不多,复习了下sql知识,数据库的学习就没有写下来了,就从Java怎么操作数据库开始吧. 因为这年过 ...

  9. U盘安装Win7系统教程

    U盘安装系统教程: http://wiki.jd.com/knowledge/6699.html

  10. 远程唤醒、WOL、Magic_Packet

    背景:很多人熟悉远程桌面并经常地利用它所带来的方便,但是前提是服务器(远程电脑)必须是处于开机状态.对于机房里有专人管理的服务器,这点不成问题,但如果是放在家里的电脑,要让它7*24地开机似乎就不好办 ...