POJ 2455 - Secret Milking Machine
原题地址:http://poj.org/problem?id=2455
题目大意:给出一个N个点的无向图,中间有P条边,要求找出从1到n的T条通路,满足它们之间没有公共边,并使得这些通路中经过的最长的边的长度最短。两点之间允许有重边
数据范围:2 <= N <= 200, 1 <= P <= 40,000,1 <= T <= 200,1 <= 每条路的长度L <= 1,000,000
题目分析:
看到“最大值最小”的第一反应就是二分最大长度k,满足T条通路没有公共边的第一反应就是将每条边的容量赋为1然后跑一遍最大流。这样算法就出来了:读入并建图,二分最大长度k,将所有长度小于等于 k 的边的容量设为1, 大于 k 的边容量设为0,然后以1为源点,n为汇点做一遍最大流,如果满足最大流大于等于T,则合要求继续二分,直至找出答案。
一开始在双向边建图的时候有点犹豫。毕竟网络流要求每条边必须要有反向边。最开始的想法是将每条双向边都拆成两条单向边,对每条单向边都建立一条长度为无穷大的反向边(无穷大是为了保证二分时赋初始容量都将它们为0),但是后来证明这种想法是错误的:因为题目要求每条边只能走一次,但是按我的想法每条边可以正向走一次,反向走一次,加上题目中允许有重边,就使情况变得更加复杂。后来我发现网络流的反向边不一定要初始容量为0——就算我将这一条双向边的两个方向按照网络流的一对反向边来建立,初始容量都允许为1,无论正着流还是反着流这条边所能允许的总容量必然只有0或1……然后就想通了(希望能给这里想不太清楚的同学们一点帮助)
然后这道题TLE到死……经过hockey指点才发现是我Dinic 写残了,应该到不能流的时候就退出但是我没有……改掉这一点之后,我加上当前弧优化的Dinic还是可以600+MS勉强AC的
PS:网上有些人说重新建立源点和汇点,并连接一条从源点到1的容量为T的边,其实丝毫没有必要,直接以1为源点是可以的
- //date 20140118
- #include <cstdio>
- #include <cstring>
- const int maxn = ;
- const int maxm = ;
- const int INF = 0x7FFFFFFF;
- inline int getint()
- {
- int ans(); char w = getchar();
- while('' > w || w > '')w = getchar();
- while('' <= w && w <= '')
- {
- ans = ans * + w - '';
- w = getchar();
- }
- return ans;
- }
- inline int min(int a, int b){return a < b ? a : b;}
- inline int max(int a, int b){return a > b ? a : b;}
- int n, m, T;
- int s, t;
- struct edge
- {
- int v, w, c, next;
- }E[maxm];
- int a[maxn];
- int now[maxn];
- int nedge;
- int lab[maxn];
- inline void add(int u, int v, int w, int c)
- {
- E[++nedge].v = v;
- E[nedge].c = c;
- E[nedge].w = w;
- E[nedge].next = a[u];
- a[u] = nedge;
- }
- int maxl, minl;
- inline int label()
- {
- static int q[maxn];
- int l = , r = ;
- memset(lab, 0xFF, sizeof lab);
- q[] = s; lab[s] = ;
- while(l < r)
- {
- int x = q[++l];
- for(int i = a[x]; i; i = E[i].next)
- if(E[i].c == && lab[E[i].v] == -)
- {
- lab[E[i].v] = lab[x] + ;
- q[++r] = E[i].v;
- }
- }
- return lab[t] != -;
- }
- int Dinic(int v, int f)
- {
- if(v == t)return f;
- int res = , w;
- for(int i = now[v]; i; i = now[v] = E[i].next)
- if((E[i].c == ) && (f > ) && (lab[v] + == lab[E[i].v]) && (w = Dinic(E[i].v, min(f, E[i].c))))
- {
- E[i].c -= w;
- E[i ^ ].c += w;
- f -= w;
- res += w;
- if(f == )break;
- }
- if(res == )lab[v] = -;
- return res;
- }
- inline int max_flow()
- {
- int ans = ;
- while(label())
- {
- for(int i = s; i <= t; ++i)now[i] = a[i];
- ans += Dinic(s, INF);
- }
- return ans;
- }
- inline bool check(int k)
- {
- for(int i = ; i <= nedge; i += )
- if(E[i].w <= k)E[i].c = E[i ^ ].c = ; else E[i].c = E[i ^ ].c = ;
- int ans = max_flow();
- //printf("%d\n", ans);
- return ans >= T;
- }
- inline int solve(int l, int r)
- {
- int mid;
- while(l < r)
- {
- mid = (l + r) >> ;
- if(check(mid))r = mid;
- else l = mid + ;
- }
- return l;
- }
- int main()
- {
- n = getint(); m = getint(); T = getint();
- nedge = ; maxl = ; minl = INF;
- s = ; t = n;
- int x, y, z;
- for(int i = ; i <= m; ++i)
- {
- x = getint(); y = getint(); z = getint();
- add(x, y, z, );
- add(y, x, z, );
- maxl = max(maxl, z);
- minl = min(minl, z);
- }
- int ans = solve(minl, maxl);
- printf("%d\n", ans);
- return ;
- }
小结:建图还是需要多加思考多加练习,代码模板也是需要不断完善的,加油~
POJ 2455 - Secret Milking Machine的更多相关文章
- POJ 2455 Secret Milking Machine(搜索-二分,网络流-最大流)
Secret Milking Machine Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9658 Accepted: ...
- POJ 2455 Secret Milking Machine(最大流+二分)
Description Farmer John is constructing a new milking machine and wishes to keep it secret as long a ...
- POJ 2455 Secret Milking Machine (二分 + 最大流)
题目大意: 给出一张无向图,找出T条从1..N的路径,互不重复,求走过的所有边中的最大值最小是多少. 算法讨论: 首先最大值最小就提醒我们用二分,每次二分一个最大值,然后重新构图,把那些边权符合要求的 ...
- poj 2455 Secret Milking Machine 二分+最大流 sap
题目:p条路,连接n个节点,现在需要从节点1到节点n,不重复走过一条路且走t次,最小化这t次中连接两个节点最长的那条路的值. 分析:二分答案,对于<=二分的值的边建边,跑一次最大流即可. #in ...
- POJ 2455 Secret Milking Machine (二分+无向图最大流)
[题意]n个点的一个无向图,在保证存在T条从1到n的不重复路径(任意一条边都不能重复)的前提下,要使得这t条路上经过的最长路径最短. 之所以把"经过的最长路径最短"划个重点是因为前 ...
- POJ 2455 Secret Milking Machine 【二分】+【最大流】
<题目链接> 题目大意: FJ有N块地,这些地之间有P条双向路,每条路的都有固定的长度l.现在要你找出从第1块地到第n块地的T条不同路径,每条路径上的路段不能与先前的路径重复,问这些路径中 ...
- POJ2455 Secret Milking Machine
Secret Milking Machine Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 12324 Accepted ...
- 【bzoj1733】[Usaco2005 feb]Secret Milking Machine 神秘的挤奶机 二分+网络流最大流
题目描述 Farmer John is constructing a new milking machine and wishes to keep it secret as long as possi ...
- [bzoj1733][Usaco2005 feb]Secret Milking Machine 神秘的挤奶机_网络流
[Usaco2005 feb]Secret Milking Machine 神秘的挤奶机 题目大意:约翰正在制造一台新型的挤奶机,但他不希望别人知道.他希望尽可能久地隐藏这个秘密.他把挤奶机藏在他的农 ...
随机推荐
- 最火的.NET开源项目(转)
综合类 微软企业库 微软官方出品,是为了协助开发商解决企业级应用开发过程中所面临的一系列共性的问题, 如安全(Security).日志(Logging).数据访问(Data Access).配置管理( ...
- 不借助jquery封装好的ajax,你能用js手写ajax框架吗
不借助jquery封装好的ajax,你能手写ajax框架吗?最基础的ajax框架,一起来围观吧. .创建XMLHttpRequest对象 var xhr = new XMLHttpRequest(); ...
- 有n个整数,使其前面各数顺序向后移m个位置,最后m个数变成最前面m个数。
#include<stdio.h> #include<stdlib.h> int main() { setvbuf(stdout,NULL,_IONBF,); //使用Ecli ...
- spring测试父类,使用junit-4.4.jar,spring-test.jar
@ContextConfiguration(locations = "classpath:conf/applicationContext.xml") @RunWith(Spring ...
- HDU 1540 / POJ 2892 Tunnel Warfare (单点更新,区间合并,求包含某点的最大连续个数)
题意:一条线上有n个点,D x是破坏这个点,Q x是表示查询x所在的最长的连续的点的个数,R是恢复上一次破坏的点. 思路:这题的关键是查询. 将被毁的村庄看成空位,当查询某个点的时候,如果我们知道它左 ...
- orale内置函数COALESCE和GREATEST和LEAST
1. COALESCE 返回该表达式列表的第一个非空value. 格式: COALESCE(value1, value2, value3, ...) 含义: 返回value列表第一个非空的值. val ...
- hdu 4699 Editor 模拟栈
思路:刚开始用STL中的栈,一直RE……,之后改为手动模拟栈操作,在注意点细节就可以了!!! 代码如下: #include<cstdio> #include<cstring> ...
- JScrollPane与JPanel 滚动条 解决canvas的滚动条问题
当用JScrollPane和JPanel显示图片时,需要将JPanel的PrefferedSize及时传递给JScrollPane,否则容易出现JScrollPane的滚动条无法与图片大小匹配的问题, ...
- 此版本的 SQL Server 不支持用户实例登录标志。该连接将关闭“的解决
此版本的 SQL Server 不支持用户实例登录标志.该连接将关闭“的解决(转) 2008-10-04 13:31 错误提示:说明: 执行当前 Web 请求期间,出现未处理的异常.请检查堆栈跟踪信息 ...
- hdu1068 Girls and Boys
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1068 二分图的最大独立集数=节点数(n)— 最大匹配数(m) 另外需要注意的是: 本题求出的最大匹配数是实 ...