POJ 2455 Secret Milking Machine (二分答案+最大流)

来源:互联网 发布:怎么在eclipse中看源码 编辑:程序博客网 时间:2024/05/19 18:13

本题乃网络流一大水题,但也有值得总结的地方。


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.


Solution

题目让求无向图中T条1-n的无共边路径,使得最长路径的长度最小。
分析:
1.最长路径最小,凡是要使最大的最小,最小的最大的问题,大多数都是二分答案,因为具有单调性。(你要直接枚举我也没话说,TLE等着你)剩下一小部分不是二分的本蒟蒻也不知道怎么做。哦,对了,最小生成树的最长边也是最小的最长边。
如何检验二分出的东西呢?我们要将问题转化 : 假设构出一个图满足最长边小于等于一个数mid,那么所有的边都小于或等于mid了吧?于是我们可以将mid作为“合法图”的边长度的上界。这样,加边时,超过上界的就弃掉。

2.这样构完图后,我们跑Dinic最大流检验,给每条边赋容量为1(套路,边不能重复走就想想网络流中的容量限制,想最短路可能就走远了)。这样每一条可行流就对应着一条合法路径(流量为1)。最后看看是否满流即可×,我们可加一条限制边看满流,不如直接拿最大流与T比一比。值得注意的是,本题为了降低AC率,有重边,邻接链表就不说了。其次,无向图就要注意,反向边的容量要等于正向边的容量,不能设为零!换句话说,就是直接让其反向边变成其相反边。(不过好像直接连4条边也可以。。。)
好吧,这题就这样吧。


Code:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cmath>#include <queue>#include <cstring>#define N 250#define M 40005#define INF 0x7fffffffusing namespace std;int T, n, m; int cur, head_p[N], iter[N], level[N];struct Tadj{int next, obj, cap;} Edg[M << 1];struct Save{int a, b, c;}  e[M];void Insert(int a, int b, int c){    cur ++;    Edg[cur].next = head_p[a];    Edg[cur].obj = b;    Edg[cur].cap = c;    head_p[a] = cur;}queue <int> q;void bfs(){    q.push(1);    for(int i = 1; i <= n; i++)  level[i] = -1;    level[1] = 0;    while(!q.empty()){      int now = q.front();      q.pop();      for(int i = head_p[now]; ~ i; i = Edg[i].next){        int v = Edg[i].obj, c = Edg[i].cap;        if(c && level[v] == -1){          level[v] = level[now] + 1;          q.push(v);        }      }    }}int Dinic(int now, int f){    if(now == n)  return f;    for(int &i = iter[now]; ~ i; i = Edg[i].next){      int v = Edg[i].obj, c = Edg[i].cap;      if(level[v] > level[now] && c){        int d = Dinic(v, min(f, c));        if(d){          Edg[i].cap -= d;          Edg[i^1].cap += d;          return d;        }      }    }    return 0;}int Max_flow(){    int flow = 0, f;    for(;;){      bfs();      if(level[n] == -1)  return flow;      for(int i = 1; i <= n; i++)  iter[i] = head_p[i];      while((f = Dinic(1, INF)) > 0)  flow += f;    }}bool check(int Limit){    cur = -1;    for(int i = 1; i <= n; i++)  head_p[i] = -1;    for(int i = 1; i <= m; i++){      if(e[i].c <= Limit){        Insert(e[i].a, e[i].b, 1);        Insert(e[i].b, e[i].a, 1);      }    }    return Max_flow() >= T;}int main(){    scanf("%d%d%d", &n, &m, &T);    int Max = 0;    for(int i = 1; i <= m; i++){      scanf("%d%d%d", &e[i].a, &e[i].b, &e[i].c);      Max = e[i].c > Max ? e[i].c : Max;    }    int L = 0, R = Max;    while(L + 1 < R){      int mid = (L + R) >> 1;      if(check(mid))  R = mid;      else  L = mid;    }    printf("%d\n", R);    return 0;}

服从感性,抗拒理性,不愿活着心却死去。

1 0
原创粉丝点击