题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1598
题目意思:
有n个城市,m条双向的路,每条路都有个速度要求(在该路上行驶必须为该速度),求从城市s到e路径最大速度与最小速度差的最小值。
解题思路:
二分+并查集
直接求不好求,二分可以简化问题。枚举下届,二分上届,把所有在之间的速度都加进一个集合里,判断s和e是否在一个集合里即可。在的话,再判断上届能否再减小,直到得出最优解。并查集用语判断两城市是否在一个集合内。
二分是很重要的求解问题的思路,前提是存在制约关系(也就是单调关系),能简化问题,优化问题。
代码:
//#include<CSpreadSheet.h>
#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000007
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define Maxn 2200
int n,m,k;
int be,en;
int fa[220];
struct Node
{
int a,b,va;
}node[Maxn];
bool cmp(struct Node a,struct Node b)
{
return a.va<b.va;
}
int find(int x)
{
int temp=x;
while(fa[x]!=x)
x=fa[x];
while(fa[temp]!=x)
{
int cur=fa[temp];
fa[temp]=x;
temp=cur;
}
return x;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&node[i].a,&node[i].b,&node[i].va);
//add(node[i].a,node[i].b,node[i].va);
//add(node[i].b,node[i].a,node[i].va);
}
sort(node+1,node+m+1,cmp);
scanf("%d",&k);
for(int i=1;i<=k;i++)
{
scanf("%d%d",&be,&en);
int ans=INF;
for(int j=1;j<=m;j++)
{
int Min=node[j].va; //下届 直接二分速度好些
int le=j;
int ri=m;
while(le<=ri)
{
int mid=(le+ri)>>1;
for(int i=1;i<=n;i++)
fa[i]=i;
for(int p=le-1;p>=1;p--)
{
if(node[p].va>=Min) //如果有相等的
{
int aa=find(node[p].a);
int bb=find(node[p].b);
if(aa!=bb)
{
fa[aa]=bb;
}
}
else
break;
}
for(int p=le;p<=m;p++)
{
if(node[p].va>node[mid].va)
break;
int aa=find(node[p].a);
int bb=find(node[p].b);
if(aa!=bb)
fa[aa]=bb;
}
if(find(be)==find(en)) //可到达
{
ans=min(ans,node[mid].va-Min);
ri=mid-1;
}
else
le=mid+1;
}
}
if(ans!=INF)
printf("%d\n",ans);
else
printf("-1\n");
}
}
return 0;
}