4 4 1 2 2 2 3 4 1 4 1 3 4 2 2 1 3 1 2
1 0
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define maxn 205
#define MAXN 2005
#define mod 1000000009
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
typedef long long ll;
using namespace std;
int n,m,ans,cnt,tot,flag;
int a[2005],pp[205],q[205]; // pp-相当于邻接点的头指针 q-模拟队列
bool vis[205]; // 标记数组
int s,e,mi,ma,le,ri,mid;
struct Node
{
int v,w,next;
} edge[MAXN]; // 边
void addedge(int u,int v,int w) // 建图
{
cnt++;
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].next=pp[u];
pp[u]=cnt;
}
bool bfs1()
{
int i,j,t,u,v,head=0,tail=-1;
memset(vis,0,sizeof(vis)); // 标记数组清空
vis[s]=1;
q[++tail]=s; // 起点进队列
while(head<=tail) // 当队中有元素
{
u=q[head]; // 出队首
if(u==e) return true ; // 为e则能到达
head++;
for(i=pp[u];i;i=edge[i].next) // 访问u的邻接点
{
v=edge[i].v;
if(!vis[v]&&edge[i].w>=mi)
{
vis[v]=1;
if(v==e) return true ; // 为e则能到达
q[++tail]=v;
}
}
}
return false ;
}
bool bfs2() // 和bfs1基本一样
{
int i,j,t,u,v,head=0,tail=-1;
memset(vis,0,sizeof(vis));
vis[s]=1;
q[++tail]=s;
while(head<=tail)
{
u=q[head];
if(u==e) return true ;
head++;
for(i=pp[u];i;i=edge[i].next)
{
v=edge[i].v;
if(!vis[v]&&edge[i].w>=mi&&edge[i].w<=a[mid])
{
vis[v]=1;
if(v==e) return true ;
q[++tail]=v;
}
}
}
return false ;
}
void solve()
{
int i,j,t,q;
scanf("%d",&q);
sort(a+1,a+m+1); // 将边按照权值排序
while(q--)
{
scanf("%d%d",&s,&e);
ans=INF; // 将答案出初始化为无穷大
for(i=1; i<=m; i++) // 枚举最小边
{
mi=a[i];
if(!bfs1()) break ; // 看只走边>=最小边时s能否到达e 不能则后面的都不能到达了 退出循环
le=i;
ri=m;
while(le<ri) // 二分最大值所在的数组下标
{
mid=(le+ri)>>1;
if(bfs2()) ri=mid; // 看只走边在[a[le],a[ri]]范围内 s能否到达e
else le=mid+1;
}
ans=min(ans,a[le]-mi); // 更新答案
}
if(ans==INF) ans=-1;
printf("%d\n",ans);
}
}
int main()
{
int i,j,t;
while(~scanf("%d%d",&n,&m))
{
int u,v,w;
cnt=0;
memset(pp,0,sizeof(pp));
for(i=1; i<=m; i++)
{
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w); // 建图
addedge(v,u,w);
a[i]=w; // 记录权值
}
solve();
}
return 0;
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define maxn 1005
#define MAXN 2005
#define mod 1000000009
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
typedef long long ll;
using namespace std;
int n,m,ans,cnt,tot,flag;
struct Node
{
int u,v,w;
}edge[maxn];
int s,e;
int pre[205];
bool cmp(Node xx,Node yy) // 排序用的比较函数
{
return xx.w<yy.w;
}
int Find(int x) // 递归找到根节点
{
if(x==pre[x]) return x;
pre[x]=Find(pre[x]);
return pre[x];
}
void Merge(int x,int y) // 合并集合
{
int u=Find(x),v=Find(y);
if(u!=v) pre[u]=v;
}
void solve()
{
int i,j,t,q;
scanf("%d",&q);
sort(edge+1,edge+m+1,cmp); // 按照边权值排序
while(q--)
{
scanf("%d%d",&s,&e);
ans=INF;
for(i=1; i<=m; i++) // 枚举最小边
{
for(j=1;j<=n;j++) pre[j]=j; // 并查集初始化
for(j=i;j<=m;j++) // 枚举最大边
{
Merge(edge[j].u,edge[j].v);
if(Find(s)==Find(e)) break ;
}
if(j<=m) // 能到达则更新ans
{
ans=min(ans,edge[j].w-edge[i].w);
}
}
if(ans==INF) ans=-1;
printf("%d\n",ans);
}
}
int main()
{
int i,j,t;
while(~scanf("%d%d",&n,&m))
{
for(i=1; i<=m; i++)
{
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
}
solve();
}
return 0;
}
hdu 1598 find the most comfortable road (二分+bfs 或者 并查集),布布扣,bubuko.com
hdu 1598 find the most comfortable road (二分+bfs 或者 并查集)
原文:http://blog.csdn.net/tobewhatyouwanttobe/article/details/20924347