如何解决图时间复杂度
最近我参加了Google的编码考试,并且对Graph数据结构有疑问, 问题之一是,他们给出了具有N个节点和M个边的无向图G,他给出了Q个查询,在每个查询中,他给出了XYW,在这里我们必须检查从X到Y的每个边是否存在路径必须最多包含权重
每当我使用矩阵表示形式时,都会超出内存限制;如果使用邻接列表表示形式,则会超过时间限制。Question Image
顺便说一下,考试是几天前完成的。
这是我的第一个问题。如果我有任何错误,请在下面评论
解决方法
这可以在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,v});
}
for(int i=0; i<q; i++)
{
int x,W;
cin>>x>>y>>W;
queries.push_back({W,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":" ");
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。