Skip to content

Latest commit

 

History

History
 
 

1782.Count-Pairs-Of-Nodes

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

1782.Count-Pairs-Of-Nodes

我们可以很容易地求出每个节点的边的数目count[i]. 那么属于一个节点{a,b}的边的数目就是count[a]+count[b]-num[a][b],其中num[a][b]就是从a到b的边的数目(因为可能会有重复的边)。减去的这部分,是因为“a-b”这条边被两个节点共享,所以count[a]和count[b]重复计算了两次,需要减去。注意我们只需要减去一次num[a][b],而不用再减去num[b][a]。

假设query的数值是x,那么我们需要寻找有多少个点对{a,b},满足count[a]+count[b]-num[a][b] > x。暴力枚举{a,b}的话,那需要o(N^2)的时间,显然会TLE。

我们发现,如果不考虑num[a][b]这部分,那么点对{a,b}的数目其实可以用o(VlogV)的时间复杂度计算。将count排序后,如果固定a指针,那么b指针相应地从后往前移动直到不满足count[a]+count[b]>x为止,那么说明以a为第一个点时,b有n-b-1种选择。这样我们依次遍历所有的a,就可以累加得到所有{a,b}的点对数目count。

以上的count其实是一个被高估的数目。因为很多点对不满足count[a]+count[b]-num[a][b] > x。那么如何排除掉这些不满足条件的点对呢?难道还是要枚举a和b呢?其实这里有一个巧妙的视角。满足count[a]+count[b] > x但是不满足count[a]+count[b]-num[a][b] > x的点对,一定是有边互联的点对。所以我们只需要遍历所有的边,查看这条边所连接的两个节点是否属于被“误判”的点对。是的话,从count里面减去就行了。

这里需要注意的是,因为有重复的边,所以我们只能遍历所有unique的边。否则被“误判”的点对可能会被删除多次。为了标记unique的边,我们可以用边的两个端点a和b编码成一个index=a*M+b,其中a<b。这样连接同一对点的边都会有独一无二的index。