这可以在O(n log n + q log q) 中解决,而您的 DFS 解决方案是 O(m*q),而 adj 矩阵解决方案是 O(n^2) 空间
要快速解决这个问题,您需要了解 DSU(Disjiont Set Union)数据结构(也称为 Union Find)。支持O(log n)部分节点的高效联合,O(log n)中也可以判断部分节点是否连接
- 按权重对所有给定边进行升序排序
- 按权重、升序对所有给定查询进行排序(同时保存查询索引,因为需要按顺序输出)
- 现在一一处理查询,如果查询请求带有边
<= w 的路径,则将所有仍未添加的边添加到符合条件的图中(使用 DSU)
- 现在可以通过检查
start end 查询的节点是否连接来回答查询(使用DSU)
示例代码(C++):
#include <bits/stdc++.h>
using namespace std;
int Find(int u, vector<int>&P)
{
return P[u] < 0 ? u : P[u] = Find(P[u],P);
}
void Union(int u, int v, vector<int>&P)
{
u=Find(u,P);
v=Find(v,P);
if(u==v)return;
P[u]=v;
}
int main()
{
//input is quite large so we might need fast I/O
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int t,n,m,q;
cin>>t;
while(t--)
{
cin>>n>>m>>q;
vector<int>P(n+1,-1),answers(q);
vector<array<int,3>>edges; //<storing edges as [w, u, v]
vector<array<int,4>>queries; //<storing queries as [W, x, y, queryId]
for(int i=0; i<m; i++)
{
int u,v,w;
cin>>u>>v>>w;
edges.push_back({w,u,v});
}
for(int i=0; i<q; i++)
{
int x,y,W;
cin>>x>>y>>W;
queries.push_back({W,x,y,i});
}
sort(edges.begin(),edges.end());
sort(queries.begin(),queries.end());
int edgeId = 0;
for(auto&query : queries){
while(edgeId < edges.size() && edges[edgeId][0] <= query[0]){
Union(edges[edgeId][1], edges[edgeId][2], P);
edgeId++;
}
answers[query[3]] = Find(query[1],P) == Find(query[2], P);
}
for(int i=0; i<q; i++)
cout<<answers[i]<<(i+1==q?"\n":" ");
}
}