poj2455 Secret Milking Machine

思路:

二分+最大流。

实现:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <limits.h>
  4 #include <string.h>
  5 #include <assert.h>
  6 #include <queue>
  7 #include <vector>
  8 #include <algorithm>
  9 #include <iostream>
 10
 11 #define N (398)
 12 #define M (N * N + 4 * N)
 13 const int INF = 0x3f3f3f3f;
 14 typedef long long LL;
 15
 16 using namespace std;
 17
 18 struct edge
 19 {
 20     int v, cap, next;
 21 };
 22 edge e[M];
 23
 24 int head[N], level[N], cur[N];
 25 int num_of_edges;
 26
 27 void dinic_init(void)
 28 {
 29     num_of_edges = 0;
 30     memset(head, -1, sizeof(head));
 31     return;
 32 }
 33
 34 int add_edge(int u, int v, int c1, int c2)
 35 {
 36     int& i = num_of_edges;
 37
 38     assert(c1 >= 0 && c2 >= 0 && c1 + c2 >= 0); // check for possibility of overflow
 39     e[i].v = v;
 40     e[i].cap = c1;
 41     e[i].next = head[u];
 42     head[u] = i++;
 43
 44     e[i].v = u;
 45     e[i].cap = c2;
 46     e[i].next = head[v];
 47     head[v] = i++;
 48     return i;
 49 }
 50
 51 int dfs(int u, int t, int bn)
 52 {
 53     if (u == t) return bn;
 54     int left = bn;
 55     for (int &i = cur[u]; i >= 0; i = e[i].next)
 56     {
 57         int v = e[i].v;
 58         int c = e[i].cap;
 59         if (c > 0 && level[u] + 1 == level[v])
 60         {
 61             int flow = dfs(v, t, min(left, c));
 62             if (flow > 0)
 63             {
 64                 e[i].cap -= flow;
 65                 e[i ^ 1].cap += flow;
 66                 cur[u] = i;
 67                 left -= flow;
 68                 if (!left) break;
 69             }
 70         }
 71     }
 72     if (left > 0) level[u] = 0;
 73     return bn - left;
 74 }
 75
 76 bool bfs(int s, int t)
 77 {
 78     memset(level, 0, sizeof(level));
 79     level[s] = 1;
 80     queue<int> q;
 81     q.push(s);
 82     while (!q.empty())
 83     {
 84         int u = q.front();
 85         q.pop();
 86         if (u == t) return true;
 87         for (int i = head[u]; i >= 0; i = e[i].next)
 88         {
 89             int v = e[i].v;
 90             if (!level[v] && e[i].cap > 0)
 91             {
 92                 level[v] = level[u] + 1;
 93                 q.push(v);
 94             }
 95         }
 96     }
 97     return false;
 98 }
 99
100 LL dinic(int s, int t)
101 {
102     LL max_flow = 0;
103
104     while (bfs(s, t))
105     {
106         memcpy(cur, head, sizeof(head));
107         max_flow += dfs(s, t, INT_MAX);
108     }
109     return max_flow;
110 }
111
112 int n, p, t;
113 struct Edge
114 {
115     int a, b, cost;
116 };
117 Edge es[40005];
118
119 bool check(int x)
120 {
121     dinic_init();
122     for (int i = 0; i < p; i++)
123     {
124         if (es[i].cost <= x)
125         {
126             add_edge(es[i].a, es[i].b, 1, 0);
127             add_edge(es[i].b, es[i].a, 1, 0);
128         }
129     }
130     return dinic(1, n) >= t;
131 }
132
133 int main()
134 {
135     scanf("%d %d %d", &n, &p, &t);
136     int maxn = 0;
137     for (int i = 0; i < p; i++)
138     {
139         scanf("%d %d %d", &es[i].a, &es[i].b, &es[i].cost);
140         maxn = max(maxn, es[i].cost);
141     }
142     int l = 0, r = maxn, ans = INF;
143     while (l <= r)
144     {
145         int m = (l + r) >> 1;
146         if (check(m))
147         {
148             r = m - 1; ans = m;
149         }
150         else l = m + 1;
151     }
152     printf("%d\n", ans);
153     return 0;
154 }

原文地址:https://www.cnblogs.com/wangyiming/p/8280059.html

时间: 2024-10-15 11:59:41

poj2455 Secret Milking Machine的相关文章

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

题目大意:N个点P条边,令存在T条从1到N的路径,求路径上的边权的最大值最小为多少 思路:做了好多二分+最大流的题了,思路很好出 二分出最大边权后建图,跑dinic 问题是....这题是卡常数的好题!!!!! T了8发以后实在受不了,瞄了眼网上的程序,齐刷刷的邻接矩阵....论邻接矩阵的优越性 但不信邪的我终于反复优化常数后邻接表A了 //TLE的程序 #include <stdio.h> #include <iostream> #include <string.h>

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

POJ 2455 Secret Milking Machine 题目链接 题意:一个无向图,要求有T条不重复道路可以从1走到t,问道路中最大边的最小值可以是多少 思路:二分+最大流,二分长度,连起边,注意是无向图,所以反向边是有容量的,然后源点和1连容量t,n和汇点连容量是t 代码: #include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespa

POJ 2455 Secret Milking Machine(搜索-二分,网络流-最大流)

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

【bzoj1733】[Usaco2005 feb]Secret Milking Machine 神秘的挤奶机 二分+网络流最大流

题目描述 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 <=

poj 2455 Secret Milking Machine 【二分 + 最大流】 【1到N不重复路径不少于T条时,求被选中路径上的最大边权值 的最小值】

Secret Milking Machine Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10620   Accepted: 3110 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

[bzoj1733][Usaco2005 feb]Secret Milking Machine 神秘的挤奶机_网络流

[Usaco2005 feb]Secret Milking Machine 神秘的挤奶机 题目大意:约翰正在制造一台新型的挤奶机,但他不希望别人知道.他希望尽可能久地隐藏这个秘密.他把挤奶机藏在他的农场里,使它不被发现.在挤奶机制造的过程中,他需要去挤奶机所在的地方T(1≤T≤200)次.他的农场里有秘密的地道,但约翰只在返回的时候用它.农场被划分成N(2≤N≤200)块区域,用1到200标号.这些区域被P(1≤P≤40000)条道路连接,每条路有一个小于10^6的长度L.两块区域之间可能有多条

[BZOJ 1733] [Usaco2005 feb] Secret Milking Machine 【二分 + 最大流】

题目链接:BZOJ - 1733 题目分析 直接二分这个最大边的边权,然后用最大流判断是否可以有 T 的流量. 代码 #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const int MaxN = 200 + 5,

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

题目大意: 给出一张无向图,找出T条从1..N的路径,互不重复,求走过的所有边中的最大值最小是多少. 算法讨论: 首先最大值最小就提醒我们用二分,每次二分一个最大值,然后重新构图,把那些边权符合要求的边加入新图,在新图上跑网络流. 这题有许多注意的地方: 1.因为是无向图,所以我们在加正向边和反向边的时候,流量都是1,而不是正向边是1,反向边是0. 2.题目中说这样的路径可能不止t条,所以我们在最后二分判定的时候不能写 == t,而是要 >= t. 3.这题很容易T ,表示我T了N遍,弱菜啊.

BZOJ 1733: [Usaco2005 feb]Secret Milking Machine 神秘的挤奶机

Description 约翰正在制造一台新型的挤奶机,但他不希望别人知道.他希望尽可能久地隐藏这个秘密.他把挤奶机藏在他的农场里,使它不被发现.在挤奶机制造的过程中,他需要去挤奶机所在的地方T(1≤T≤200)次.他的农场里有秘密的地道,但约翰只在返回的时候用它.农场被划分成N(2≤N≤200)块区域,用1到200标号.这些区域被P(1≤P≤40000)条道路连接,每条路有一个小于10^6的长度L.两块区域之间可能有多条道路连接.为了减少被发现的可能,约翰不会两次经过农场上的任何一条道路.当然了