题意:
给N个城市和M条路。然后告诉每条路的起点和终点以及这条路的舒适度。接着是Q个询问,对每个询问的st,ed,求从st到ed这中间的路中舒适度最大值与最小值的差。
解题思路:
用结构体将每条路的端点和舒适度存起来,然后对舒适度进行从小到大排序。接着枚举每条最小的边(for(0..m)),利用克鲁斯卡尔方法,将每条边加入一个集合中,直到起点和终点在一个集合中,更新最大值和最小值的差。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 200+10;
const int M = 1000+10;
const int INF = 1<<27;
int root[N];
int n;
struct Node
{
int x,y,w;
friend bool operator < (const Node a,const Node b)
{
return a.w < b.w;
}
} edge[M];
void init()
{
for(int i=1;i<=N;i++) root[i]=i;
return;
}
int find(int x)
{
int y=x;
while(y!=root[y]) y=root[y];
while(x!=root[x])
{
int px=root[x];
root[x]=y;
x=px;
}
return y;
}
void Union(int x,int y)
{
int fx=find(x);
int fy=find(y);
if(fx==fy) return;
root[fx]=fy;
return;
}
int main()
{
int m;
while(~scanf("%d %d",&n,&m))
{
int t=0;
memset(edge,0,sizeof(edge));
while(m--)
{
int x,y,w;
scanf("%d %d %d",&x,&y,&w);
edge[t].x=x;//存边
edge[t].y=y;
edge[t].w=w;
t++;
}
int Q;
sort(edge,edge+t);//将舒适度从小到大排序
scanf("%d",&Q);
while(Q--)
{
int x,y;
scanf("%d %d",&x,&y);
int mis=INF;
for(int i=0;i<t;i++)//枚举最小的边
{
init();//每次都初始化憋忘了。。
int j;
for(j=i;j<t;j++)//搜索最大的边
{
Union(edge[j].x,edge[j].y);
if(find(x)==find(y))//直到x,y在一个结合为止
{
mis=min(mis,edge[j].w-edge[i].w);//因为已经排序,可直接更新
break;
}
}
if(j==t) break;//一个小优化
}
if(mis==INF) printf("-1\n");
else printf("%d\n",mis);
}
}
return 0;
}