求上下界 差值 最小 一类问题 hdu1598 && poj3189(妙啊)

7 篇文章 0 订阅
3 篇文章 0 订阅

最开始的时候做过hdu1598,题意就是问一些点对,求一个差值最小构成的公路集合能连通这个点对,开始的时候没有具体想法,感觉上下界存在不确定性,后来就枚举上下界,通过并查集依次往里面加边,确定出此时最小的上界.

    今天做到了poj3189,也是一样的原理,给定一堆顺序,要求出顺序最小的边集,能够满足匹配,不小心看到了风神题解上写的二分字样,二分是最大流里面很常见的一个技巧,利用最大流来判定一个问题,利用二分来加速.也就联想到了hdu1598这道题目.二分当然是可以的,枚举了下界之后用二分来判定上界.但是由于网络流的一些特性,每次重新建图之后跑最大流是比较费时的.可不可以也通过类似上面那道题目类似的方法往图中添加边集,每次求出最大流,这样就可以很好地利用原来跑完最大流之后剩下来的残留网络,速度会快很多,加上这道题目里面数据里谷仓比较小.

    用这种方法比较顺利的ac了,时间还挺快(不比二分慢),也印证了上面想法还是比较正确的.

    所以这种给出一些特征值,求出满足条件的最小特征值之差 的问题,比较通过的想法就是枚举下界,然后通过二分或者是枚举出上界,具体还是需要看题目的数据范围及操作方法.

思路:一开始以为是最短路,用dijkstra写了好几遍,wawa致死,仔细审题一看,发现是要你去求最大速度与最小速度之差最小的路!最大最小之差最小,那么我们就可以联想到贪心的问题了,这题还有个地方在于能到达目的地,那么就是说明要连通给定的起点与终点了,所以我们可以考虑并查集的思想了!

所以本题的大致的思路可以确定为,我们可以对所有边的权值就行排序,然后从0开始对所有的点进行枚举,连通所有的点,看下find(a)是不是等于find(b),等于我们就可以进行拿此时的最大值与最小值作差就可以了!

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int fa[222];
const int inf=0x3f3f3f3f;
int n,m;
struct node
{
 int x,y,d;
}s[1111];
bool cmp(const node &a,const node &b){
 return a.d<b.d;
}
int find(int x){
 return x==fa[x]?x:fa[x]=find(fa[x]);
}
void Union(int x,int y)
{
 x=find(x);
 y=find(y);
 if(x!=y){fa[x]=y;}
}
int slove(int x,int y){
 int min,max,i,j,k;
 min=inf;
 for(i=0; i<m; i++){
  for(j=1; j<=n; j++)fa[j]=j;
  for(j=i; j<m; j++){
   Union(s[j].x,s[j].y);
   if(find(x)==find(y)){//一旦两者联通,两者速度即相减
    max=s[j].d-s[i].d;// 两者速度即相减。
    if(max<min){
     min=max;//取最小的差值。
     break;
    }
   }
  }
 }
 if(min==inf) return -1;
 else return min;
}
int main(void){
 int i,j,k,l;
 int x,y,q;
 while(scanf("%d%d",&n,&m)==2){
  for(i=0; i<m; i++)
   scanf("%d%d%d",&s[i].x,&s[i].y,&s[i].d);
  sort(s,s+m,cmp);
  scanf("%d",&q);
  while(q--){
   scanf("%d%d",&x,&y);
   printf("%d\n",slove(x,y));
  }
 }
}


ps:姑娘加油啊!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值