[HDU1598]find the most comfortable road
思路:
考虑一个暴力:枚举最大的边权和最小的边权,然后将边权在这之间的边全拿出来构成一张无向图,剩下的就是判断是否存在一条从$S$到$T$的路径。
相当于判$S$和$T$是否连通,用并查集连一下即可。
时间复杂度:O(m³α(n))
考虑优化,枚举了最小边权之后,从小到大枚举最大边权,每次能新添加一条边。
因为并查集是支持动态加边的,所以复杂度就降到O(m²α(n))了。
一开始存边的vector忘记每次清零,一直Wrong Answer。
1 #include<cstdio> 2 #include<vector> 3 #include<algorithm> 4 const int inf=0x7fffffff; 5 struct Edge { 6 int from,to,w; 7 bool operator < (const Edge &x) const { 8 return w<x.w; 9 } 10 }; 11 std::vector<Edge> e; 12 inline void add_edge(const int u,const int v,const int w) { 13 e.push_back((Edge){u,v,w}); 14 } 15 const int N=201; 16 class DisjointSet { 17 private: 18 int anc[N]; 19 int Find(const int x) { 20 return x==anc[x]?x:anc[x]=Find(anc[x]); 21 } 22 public: 23 void reset(const int n) { 24 for(int i=1;i<=n;i++) anc[i]=i; 25 } 26 bool isConnected(const int x,const int y) { 27 return Find(x)==Find(y); 28 } 29 void Union(const int x,const int y) { 30 anc[Find(x)]=Find(y); 31 } 32 }; 33 DisjointSet s; 34 int main() { 35 int n,m; 36 while(~scanf("%d%d",&n,&m)) { 37 e.clear(); 38 while(m--) { 39 int s,t,w; 40 scanf("%d%d%d",&s,&t,&w); 41 add_edge(s,t,w); 42 } 43 std::sort(e.begin(),e.end()); 44 int q; 45 scanf("%d",&q); 46 while(q--) { 47 int S,T; 48 scanf("%d%d",&S,&T); 49 int ans=inf; 50 for(unsigned i=0;i<e.size();i++) { 51 s.reset(n); 52 for(unsigned j=i;j<e.size();j++) { 53 int &u=e[j].from,&v=e[j].to; 54 if(!s.isConnected(u,v)) { 55 s.Union(u,v); 56 if(s.isConnected(S,T)) { 57 ans=std::min(ans,e[j].w-e[i].w); 58 break; 59 } 60 } 61 } 62 } 63 printf("%d\n",ans!=inf?ans:-1); 64 } 65 } 66 return 0; 67 }