C++ 给出一个DI图。检查对于所有节点对,是否存在来自(u,v)或(v,u)的路径

C++ 给出一个DI图。检查对于所有节点对,是否存在来自(u,v)或(v,u)的路径,c++,data-structures,graph,C++,Data Structures,Graph,如果我有一个Di图。如何检查此图的所有节点对(u,v)是否相关? 关系表示[u,v]或[v,u]之间存在连接 下面是一个例子: 在此图像中,最左边的图形在所有对之间具有关系。正确的一个不是 为了解决这个问题,我试着从原始的给定图和它的反向图中选择BFS。 我们有一个相关图,当且仅当所有节点都被两个BF访问时。 否则,图表就不相关了 #include <stdio.h> #include <vector> #include <queue> #include &

如果我有一个Di图。如何检查此图的所有节点对(u,v)是否相关?
关系表示[u,v]或[v,u]之间存在连接

下面是一个例子:
在此图像中,最左边的图形在所有对之间具有关系。正确的一个不是

为了解决这个问题,我试着从原始的给定图和它的反向图中选择BFS。 我们有一个相关图,当且仅当所有节点都被两个BF访问时。 否则,图表就不相关了

#include <stdio.h>
#include <vector>
#include <queue>
#include <string.h>

using namespace std;

typedef vector<int> vi;
typedef vector<vi> vii;

void DFS(bool *vst,vii &G,int ini){

    queue<int> q;
    q.push(ini);

    int cur;
    while(!q.empty()){
        cur = q.front();
        q.pop();

        if(vst[cur])
            continue;

        vst[cur] = true;

        vi &adj = G[cur];
        for (vi::iterator it = adj.begin(); it != adj.end(); ++it)
            q.push(*it);
    }
}

int main(void){
    //N is the number of Nodes and M is the number of Edges
    int n,m;
    scanf("%d %d",&n,&m);

    vii G(n+1); //graph
    vii R(n+1);//reversed graph

    //read and fill both graphs
    for (int i = 0,u,v; i < m; ++i) {
        scanf("%d %d",&u,&v);
        G[u].push_back(v);
        R[v].push_back(u);
    }

    //get some node with outdegree and indegree > 0
    int S = -1;
    for (int i = 1; i <= n; ++i){
        if(G[i].size() > 0  && R[i].size() > 0){
            S = i;
            break;
        }
    }

    bool vst1[n+1];
    bool vst2[n+1];
    for (int i = 1; i <= n; ++i)
        vst1[i] = vst2[i] = false;


    if(S != -1){
        DFS(vst1, G, S);
        DFS(vst2, R, S);
    }

    int i;
    for (i = 1; i <= n; ++i){
        if((vst1[i] || vst2[i]) == false){
            i = -1;
            break;
        }
    }

    if(i == n+1)
        puts("All pairs related");
    else
        puts("All pairs not-related");
}
#包括
#包括
#包括
#包括
使用名称空间std;
typedef向量vi;
病毒载体vii型;
无效DFS(bool*vst、vii&G、int ini){
队列q;
q、 推送(ini);
int cur;
而(!q.empty()){
cur=q.front();
q、 pop();
if(vst[cur])
继续;
vst[cur]=真;
vi&adj=G[cur];
对于(vi::迭代器it=adj.begin();it!=adj.end();++it)
q、 推动(*it);
}
}
内部主(空){
//N是节点数,M是边数
int n,m;
scanf(“%d%d”,&n,&m);
vii G(n+1);//图
vii R(n+1);//逆图
//阅读并填写两个图表
对于(int i=0,u,v;i0的某个节点
int S=-1;
对于(int i=1;i 0&&R[i].size()>0){
S=i;
打破
}
}
bool-vst1[n+1];
bool-vst2[n+1];

对于(inti=1;iSo),可以使用任何图遍历BFS或DFS轻松检查这一点

我假设这个定义

A directed graph is connected if for all pairs (u,v), there exists a directed path from u 
to v OR there exists a directed path from v to u.
首先检查图是否强连接,如果是,则确定图是连接的,如果不是,则按以下步骤进行:

There is no path from v to S and also from S to v.
从任何源顶点S开始图遍历,其中S必须同时具有indegree和outdegree>0,如果我们没有此类类型的顶点,则图未连接(最后的原因)

现在将访问的所有顶点标记为集合S1的元素

然后反转图形,再次从相同的源顶点S开始图形遍历

再次将访问的所有顶点标记为集合S2的元素

图是连通的当且仅当

S1 U S2 = V
用矛盾来证明

让我们假设上面的算法是错误的,并且假设图是连通的,即使

S1 U S2 is proper subset of V.
但如果s1u S2是V的一个适当子集,则必须有一个顶点V,在两次遍历中都保持不变,这意味着:

There is no path from v to S and also from S to v.
因此矛盾,因此我们的初始假设是错误的,在S1 U S2是V的适当子集的情况下,图不能连通

现在取任意一对顶点(u,v)

案例1:

S1 and S2 both contained u and v, which means that there is a directed path
from u to v and also from v to u.
案例2:

u and v are in different sets,still there exists a path from u to v OR from
v to u.
案例3:

Both u and v are in same set.
考虑下图:

假设我们从X开始第一次遍历,那么我们有:

S1={X,Y,e}

S2={X}

很明显,S1 U S2=V,但对(Y,e)没有路径这就是为什么源顶点必须同时具有indegree和outdegree>0的原因,而X显然没有,而且实际上没有任何顶点满足此条件,因此图形是不连通的。

如果有一些路径需要向前和向后移动的混合,该怎么办?@Felipe这是一个相当简单的算法。但我知道我已经用Java实现了它。@Sumeet你能解释一下吗?我的方法是正确的还是不能解决问题?@Sumeet我知道Java=)@Felipe你想让我解释算法还是代码,还是两者都要解释。我认为它解决不了问题=(。因为此算法检查所有图形对是否都有指向u、v和v、u的路径。我需要一个算法来检查所有图形对是否都有来自u、v或v、u的路径。@Felipe很抱歉,从未见过or,将更新我的答案。没问题。谢谢你的帮助。你不需要道歉=)我已经尝试过实现它,但仍然有相同的错误百分比;