我有以下图表:
directed graph http://i62.tinypic.com/sx2hqc.png
最佳解决方案是从顶点(3)启动dfs然后我将获得一个组件,但是当我们从顶点(1)启动dfs然后(3)我将得到两个组件。 问题是: 我想知道这个图表中有多少个组件?或者换句话说,覆盖所有图表所需的最小dfs数量是多少?
执行此操作所需的算法是什么?
答案 0 :(得分:0)
你混淆了两个定义。
对于无向图,有connected components的概念,您可以通过在无向图上执行DFS找到它。
对于有向图,有strongly connected components的概念,有多种算法可用,所有算法都比简单的DFS稍微复杂一些。
您应该做什么取决于您需要的两个概念中的哪一个。您的图表在被视为无向图时具有一个连接的组件,在被视为有向图时具有两个强连接的组件。
答案 1 :(得分:0)
为解决此问题,我们的想法是处理IN边缘的邻接列表。
以具有3个节点和2个边线(0,1)和(0,2)的图为例,而(a,b)表示如果您切换光源a,那么光源b也将被切换。 / p>
OUT-edges adjacency list:
0 -> 1, 2
1 -> _
2 -> _
IN-edges adjacency list:
0 -> _
1 -> 0
2 -> 0
假设我们没有周期,如果我们沿着IN边缘向下移动,直到到达没有孩子的节点,您就会得到我所谓的“影响者”,也就是说,您无法使用任何其他节点。
现在要考虑周期问题,我将检查是否有邻居或有影响者。如果不是这种情况,并且所有邻居都已被访问过,那么我会遇到一个循环并使当前节点成为影响者。
这是我的代码(在我的办公桌上通过简单的示例进行了测试):
private int numberOfLights(){
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
List<List<Integer>> inAdjList = new ArrayList<List<Integer>>();
for(int i = 0; i < n; i++){
inAdjList.add(new ArrayList<>());
}
for(int i = 0; i < n; i++){
int from = scanner.nextInt();
int to = scanner.nextInt();
inAdjList.get(to).add(from);
}
int[] visited = new int[n];
int[] isOrHasInfluencer = new int[n];
List<Integer> influencers = new ArrayList<>();
for(int i = 0; i < n; i++){
if(!visited[i]){
DFS(i, visited, isOrHasInfluencer, influencers, inAdjList);
}
}
return influencers.size();
}
private void DFS(Integer cur, int[] visited, int[] isOrHasInfluencer, List<Integer> influencers, List<List<Integer>> inAdjList){
visited[cur] = true;
boolean hasUnvisitedChildren = false;
for(Integer neighbor : inAdjList.get(cur)){
if(!visited[neighbor]){
hasUnvisitedChildren = true;
DFS(neighbor, visited, isOrHasInfluencer, influencers, inAdjList);
}
if(isOrHasInfluencer[neighbor]){
isOrHasInfluencer[cur] = true;
}
}
if(!hasUnvisitedChildren && !isOrHasInfluencer[cur]){
isOrHasInfluencer[cur] = true;
influencers.add(cur);
}
}
希望有帮助! :)
答案 2 :(得分:0)
您可以从每个节点运行findConnectedComponent算法,并返回最小数目以解决您的特定问题。 我认为该解决方案不是最佳解决方案,但对中小型输入图效果很好。
答案 3 :(得分:0)
我为这个问题奋斗了数周 最终,当我在Codechef的一场编码比赛中遇到一个问题时,找到了解决方案。
解决过程:
在您的情况下,进行拓扑排序后,我们得到3 1 2 4 现在再次根据排序后的值运行DFS(此处以3开头),您将获得ans 1。
希望有帮助:)
答案 4 :(得分:0)
我相信您正在尝试找到弱连接的组件。 测试有向图是否弱连接很容易在线性时间内完成。只需将所有边缘变成无方向的边缘,然后使用基于DFS的连接组件算法即可。
答案 5 :(得分:0)
我知道这是一个旧线程,但添加我如何解决问题会很有帮助:
1 - 找到图中的强连通分量 (SCC),对于每个 SCC,我们可以用代表该 SCC 的单个节点替换它。
2 - 现在,通过查看新图中节点的度数,我们可以知道可以从中运行 DFS 并覆盖所有其他节点的最小节点数,因此我们可以从具有 <强>度数为零。
答案 6 :(得分:0)
老问题,但还有另一种方法。