[BZOJ1733] [Usaco2005 feb]Secret Milking Machine 神秘的挤奶机

题目描述

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.
约翰正在制造一台新型的挤奶机,但他不希望别人知道.他希望尽可能久地隐藏这个秘密.他把挤奶机藏在他的农场里,使它不被发现.在挤奶机制造的过程中,他需要去挤奶机所在的地方T(1≤T≤200)次.他的农场里有秘密的地道,但约翰只在返回的时候用它.农场被划分成N(2≤N≤200)块区域,用1到200标号.这些区域被P(1≤P≤40000)条道路连接,每条路有一个小于10^6的长度L.两块区域之间可能有多条道路连接.为了减少被发现的可能,约翰不会两次经过农场上的任何一条道路.当然了,他希望走最短的路. 请帮助约翰寻找这T次从仓库走到挤奶机所在地的路线.仓库是区域1,挤奶机所在地是区域N.我们现在要求的是约翰经过的这些道路中最长的路的长度最小是多少,当然他不能重复走某一条路.请注意,我们要求的不是最短的总路程长度,而是所经过的直揍连接两个区域的道路中最长的道路的最小长度. 数据保证约翰可以找到T条没有重复的从仓库到挤奶机所在区域的路.

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.

    第1行是3个整数N、P和T,用空格隔开.
    第2到P+1行,每行包括3个整数,Ai,Bi,Li.表示区域Ai、Bi之间有一条长度为Li的道路.

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

约翰选择1-2-3-7和1-6-7两条路线.这些路线中最长路的最小长度是5

题目分析

二分路径长度 将每条边权>mid的边加入图中跑最大流 看看满足条件的路径条数是否大于T即可

#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std;
int n,m;
int tot=1,head[210],to[200010],net[200010];
int val[200010];
int s,t;
void add(int x,int y,int c)
{
    net[++tot]=head[x],head[x]=tot,to[tot]=y,val[tot]=c;
    net[++tot]=head[y],head[y]=tot,to[tot]=x,val[tot]=0;
}
int dis[210];
int x[100010],y[100010],len[100010];
int bfs()
{
    queue<int>q;
    memset(dis,0,sizeof dis);
    q.push(s);
    dis[s]=1;
    while(q.size())
    {
        int nmp=q.front();
        q.pop();
        for(int i=head[nmp];i;i=net[i])
            if(val[i]>0&&!dis[to[i]])
            {
                dis[to[i]]=dis[nmp]+1;
                q.push(to[i]);
                if(to[i]==t) return 1;
            }
    }
    return 0;
}
int dinic(int x,int flow)
{
    int tmp,temp=flow;
    if(x==t) return flow;
    for(int i=head[x];i;i=net[i])
        if(val[i]>0&&dis[to[i]]==dis[x]+1)
        {
            tmp=dinic(to[i],min(val[i],temp));
            if(!tmp) dis[to[i]]=0;
            temp-=tmp,val[i]-=tmp,val[i^1]+=tmp;
            if(!temp) break;
        }
    return flow-temp;
}
int k;
int check(int mid)
{
    memset(head,0,sizeof head);
    tot=1;
    s=1,t=n;
    int sum=0;
    for(int i=1;i<=m;i++)
        if(len[i]<=mid) add(x[i],y[i],1),add(y[i],x[i],1);
    while(bfs()) sum+=dinic(s,1<<30);
    return sum>=k;
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    int l=0,r=0,mid,ans;
    for(int i=1;i<=m;i++) scanf("%d%d%d",&x[i],&y[i],&len[i]),r=max(r,len[i]);
    while(l<=r)
    {
        mid=(l+r)>>1;
        if(check(mid)) r=mid-1,ans=mid;
        else l=mid+1;
    }
    printf("%d",ans);
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注