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. //相当于深拷贝一份dataArray。这样才不会改变dataArray本身的值

    //相当于深拷贝一份dataArray.这样才不会改变dataArray本身的值 NSMutableArray* commitDataArray = [NSKeyedUnarchiver unarch ...

  2. GBK转utf-8,宽字符转窄字符

    //GBK转UTF8 string CAppString::GBKToUTF8(const string & strGBK) { string strOutUTF8 = "" ...

  3. LOJ 1341 Aladdin and the Flying Carpet(质因子分解)

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1341 题意:给两个数a,b,求满足c * d = a且c>=b且d>=b的 ...

  4. 手机测试Android程序

    手机测试Android程序   上传者:sanpi329     我也要“分享赚钱” 2014/7/9 关注(23) 评论(0)   声明:此内容仅代表网友个人经验或观点,不代表本网站立场和观点.   ...

  5. java 类排序

    参考文档:Java排序: Comparator vs Comparable 入门 java类经常面临排序问题,据我所知:java提供comparable和comparator两种比较方式: 1. co ...

  6. DC游戏《斑鸠》原创赏析[转载]

    游戏背景:      凤来之国本来只是边远地区的一个小国.但现在他们却自称为得到“神之力”的“神通者”,在“选民思想”“和平统一”之类的名义下开始了对各地的武力侵略.      事情的起因是因为凤来之 ...

  7. 盘点:移动服务 #AzureChat

    感谢大家帮助我们顺利推出史无前例的 #AzureChat.移动服务和 Notification Hub 是 Windows Azure 平台上令人振奋的服务.我们很高兴能借这次在线讨论的机会,倾听各位 ...

  8. Android学习笔记(十七)——使用意图调用内置应用程序

    使用意图调用内置应用程序 1.创建一个新的Android项目并命名为Intents,在main.xml文件里加入两个Button: <Button android:id="@+id/b ...

  9. block 解析 - 局部变量

    局部变量 block内使用局部变量,一般都是截获变量(只读),截获离block初始化最近的一次的值. 引用官方文档: Stack (non-static) variables local to the ...

  10. Ext JS学习第六天 Ext_window组件(三)

    此文用来记录学习笔记: 今天再来一个例子巩固一下学习的window: –例2: 在window中添加子组件,并讲解常用查找组件的方式: •重点分析:该实例主要针对于组件的查找进行详细的讲解,在以后的应 ...