📅  最后修改于: 2023-12-03 15:28:48.778000             🧑  作者: Mango
给定一张有向图,如果一条边(u, v)满足从点u出发能到达点v,同时从点v出发也能到达点u,则称该边是“双向边”。 现在给定一张有向图,你需要求出其中双向边的数量。
第一行包含两个整数,分别表示有向图的节点数N(N<=5000)和边数M(M<=50000)。
接下来M行,每行包含2个整数u,v,表示存在一条从u到v的有向边。
节点编号从1~N。
一个整数,表示双向边的数量。
对于每条有向边(u, v),我们可以将它看成两条无向边(u, v)和(v, u),然后判断这两条无向边是否都存在,若存在则该有向边就是一条双向边。
常规的判断无向边是否存在的方法是使用邻接表建图进行DFS或BFS遍历,但是这种方法的时间复杂度为O(N*(M+N)),因此不能通过本题。
另外一种O(MlogN)的做法,是将所有边按照起点编号、终点编号排序,然后从前往后枚举每条边,判断其是否是双向边即可。这种做法需要使用一个unordered_map来记录每条无向边是否存在,时间复杂度为O(MlogN)。
#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
using namespace std;
int main()
{
int n, m;
cin >> n >> m;
vector<pair<int, int>> edges;
unordered_map<int, unordered_map<int, bool>> mp;
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
edges.push_back({ u, v });
mp[u][v] = true;
}
int res = 0;
for (const auto& [u, v] : edges) {
if (mp[u].count(v) && mp[v].count(u)) {
res++;
}
}
cout << res << endl;
return 0;
}
该程序使用C++语言实现,思路和上文分析基本一致。使用vector记录所有边,使用unordered_map记录每条无向边是否存在,最后枚举每条边判断是否为双向边,计算双向边数量。