一开始想到用BFS,写了之后,发现有点不太行。网上查了一下别人的解法。
首先将边从小到大排序,然后从最小边开始枚举,每次取比它大的边,直到start、end属于同一个集合,即可以连通时停止。
过程类似于最小生成树。舒适感即为选取的最后一条边减去一开始的那条边,所有情况取最小值。
#include <iostream> #include <stdio.h> #include <string.h> #include <set> #include <vector> #include <queue> #include <algorithm> using namespace std; const int INF=0x3f3f3f3f; const int maxn=211; const int maxm=1010; int n,m,q,ans,s,t; struct Edge{ int u,v,speed; bool operator < (const Edge tmp) const{ return speed<tmp.speed; } }edge[maxm]; struct UF{ int father[maxn]; void init(){ for(int i=1;i<=n;i++){ father[i]=i; } } int find_root(int x){ if(father[x]!=x) father[x]=find_root(father[x]); return father[x]; } void Union(int a,int b){ int x=find_root(a); int y=find_root(b); if(x==y) return; father[y]=x; } }uf; int main() { int a,b,c; int u,v; while(scanf("%d%d",&n,&m)!=EOF){ for(int i=1;i<=m;i++){ scanf("%d%d%d",&a,&b,&c); edge[i].speed=c; edge[i].u=a; edge[i].v=b; } sort(edge+1,edge+m+1); scanf("%d",&q); for(int w=1;w<=q;w++){ int i,j; ans=INF; scanf("%d%d",&s,&t); //开始从最小边枚举 for(i=1;i<=m;i++){ uf.init(); //每次取比它大的边 for(j=i;j<=m;j++){ u=edge[j].u; v=edge[j].v; uf.Union(u,v); int x=uf.find_root(s); int y=uf.find_root(t); //若s、t再同一个集合,表明它们之间已构成联通路 if(x==y){ break; } } //取完后面所有边,但s、t仍不能连通 if(j>m) continue; //更新最小值 if(edge[j].speed-edge[i].speed<ans) ans=edge[j].speed-edge[i].speed; } if(ans<INF) printf("%d ",ans); else printf("-1 "); } } return 0; }