hrbust 1798 秘密产奶机器【二分+最大流】
2016-10-06 12:25
344 查看
秘密产奶机器 | ||||||
| ||||||
Description | ||||||
John正在建造一种新型的产奶机器并且希望可以保守住这个秘密尽可能长的时间。他已经把机器藏在了他的农场里的一个秘密场所并且他需要在接近这台机器的时候不被发现。在机器建造过程中,他必须要走T(1<=T<=200)次通向他的机器的路径。而且他有一个秘密的地下通道,但是这个通道仅仅是在返回时使用的。 农场有N(2<=N<=200)个地标(从1到N编号),并且有P(1<=P<=40000)个双向道路(从1到P编号)连接这些地标,每条道路都有一个权值w表示该路的长度(1<=w<=1000000)。 需要注意的是两个地标之间可能会有多条道路相连。 为了防止被发现,每条道路John只能够通过一次,并且他希望尽可能的短一点的路。请帮助John算出在走向目标点这T次走的路径中,他需要经过的所有道路里最长的道路最短可以是多少。 题目保证John可以找到T条通向终点的路径。 | ||||||
Input | ||||||
多组测试数据。 对于每组测试数据: 第一行输入三个整数N,P和T 接下来的P行,每行输入三个整数a,b,w分别表示有一条连接 a 和 b 地标且长度为w的道路。 | ||||||
Output | ||||||
对于每组测试数据输出一个整数表示John所需要经过的道路中最长的道路最短可以是多少。 | ||||||
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 | ||||||
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. | ||||||
Recommend | ||||||
周洲 @Hrbust |
思路:
1、首先,我们想要找这样一个值最暴力最简单的方式就是枚举,然而因为枚举一定超时,而且考虑到找到的种类数会随着枚举出来的值增加而增加,满足单调递增性,那么我们二分查找ans,设定当前枚举到的值是mid;
2、根据当前值mid建图:
①设定源点S,连入节点1,设定权值为INF,表示期望获得无数条可行路径。
②设定汇点T,将n连入汇点,设定权值为INF,表示期望获得无数条可行路径。
③将m条无向边进行判断,其两点间距离如果小于等于mid,那么建立当前边(注意是无向),设定权值为1,表示这条边只能走一次(因为找到的每一种路径都不能有重复边)。
3、然后不断在二分过程中跑最大流,跑得一次最大流,如果其maxflow>=t(注意不是正好要t种路径,而是找到t种就可以,所以是大于等于),记录ans=mid,一直二分下去,直到不能二分为止。
4、直接枚举上界为1000000会TLE,需要枚举上界为最大边权值才能过。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
struct node
{
int from;
int to;
int w;
int next;
}e[20000400];
int n,m,t,cont,ss,tt;
int divv[20000];
int cur[20000];
int head[20000];
int bian[400060][3];
void add(int from,int to,int w)
{
e[cont].to=to;
e[cont].w=w;
e[cont].next=head[from];
head[from]=cont++;
}
void getmap(int mid)
{
ss=n+1;
tt=ss+1;
cont=0;
memset(head,-1,sizeof(head));
add(ss,1,0x3f3f3f3f);
add(1,ss,0);
add(n,tt,0x3f3f3f3f);
add(tt,n,0);
for(int i=0;i<m;i++)
{
if(bian[i][2]<=mid)
{
add(bian[i][0],bian[i][1],1);
add(bian[i][1],bian[i][0],0);
add(bian[i][1],bian[i][0],1);
add(bian[i][0],bian[i][1],0);
}
}
}
int makedivv()
{
memset(divv,0,sizeof(divv));
queue<int >s;
s.push(ss);
divv[ss]=1;
while(!s.empty())
{
int u=s.front();
if(u==tt)return 1;
s.pop();
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
int w=e[i].w;
if(w&&divv[v]==0)
{
divv[v]=divv[u]+1;
s.push(v);
}
}
}
return 0;
}
int Dfs(int u,int maxflow,int tt)
{
if(u==tt)return maxflow;
int ret=0;
for(int &i=cur[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
int w=e[i].w;
if(w&&divv[v]==divv[u]+1)
{
int f=Dfs(v,min(maxflow-ret,w),tt);
e[i].w-=f;
e[i^1].w+=f;
ret+=f;
if(ret==maxflow)return ret;
}
}
return ret;
}
int Slove(int mid)
{
getmap(mid);
int ans=0;
while(makedivv()==1)
{
memcpy(cur,head,sizeof(head));
ans+=Dfs(ss,0x3f3f3f3f,tt);
}
//printf("%d %d\n",mid,ans);
if(ans>=t)
return 1;
else return 0;
}
int main()
{
while(~scanf("%d%d%d",&n,&m,&t))
{
int maxn=0;
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&bian[i][0],&bian[i][1],&bian[i][2]);
maxn=max(maxn,bian[i][2]);
}
int mid;
int ans;
int l=0;
int r=maxn+2;
while(r>=l)
{
mid=(l+r)/2;
if(Slove(mid)==1)
{
r=mid-1;
ans=mid;
}
else l=mid+1;
}
printf("%d\n",ans);
}
}
相关文章推荐
- hrbust 1798 秘密产奶机器 (最大流+二分答案)
- hrbust 1469 Wrong Answer【最大独立集---二分匹配】
- 哈理工oj/hrbust 1492 盒子【最大二分匹配】
- BZOJ 1189 HNOI 2007 紧急疏散 evacuate 二分答案 最大流
- 从给定数组中找出最大的两个数——二分递归
- UVa live6525Attacking rooks(二分最大匹配之最大匹配)
- HDU3081 使用Floyd传递关系,二分最大流
- hdu 5855 Less Time, More profit【二分+最大权闭包--最大流Dinic】
- POJ 2455 Secret Milking Machine (二分+无向图最大流)
- BZOJ4443[Scoi2015][小凸玩矩阵] 二分图最大匹配+二分
- BZOJ-3130 费用流 (听题目胡扯丶裸最大流) 二分判定+最大流+实数精度乱搞
- hrbust1632 最大的最小公倍数(欧几里得)
- poj3020 二分图 最大二分匹配
- D. R2D2 and Droid Army(二分加多维线段树查询区间最大值)
- poj 2112 Optimal Milking(二分+最大流)
- [bzoj3993][SDOI2015]星际战争-二分+最大流
- UValive3268 Jamie's Contact Groups(二分+最大流)
- poj 2391 Ombrophobic Bovines(二分+最大流)
- POJ 2112 二分+最大流
- [LeetCode 410] Split Array Largest Sum (二分答案/最大值最小化)