有向图传递闭包

目录

  • 传递闭包的定义
  • Floyd warshall 传递闭包算法
    • Floyd warshall 代码
    • 算法实现原理
    • Floyd warshall 传递闭包算法的实现
    • 时间复杂度
  • DFS 传递闭包算法
    • 算法分析
    • 代码实现
  • 例题

有向图的传递闭包是Floyd warshall 算法的一种应用(主要参考算法导论)

传递闭包的定义

对于有向图G(V,E)的传递闭包即是G(V,E),其中E{(i,j):图G中包含一条由i到j的路径}。

Floyd warshall 传递闭包算法

Floyd warshall 代码

void floyd_warshall()
{
    int tmp;
    for(int k = 1; k <= n; ++k)
    {
        for(int i = 1; i <= n; ++i)
        {
            for(int j = 1; j <= n; ++j)
            {
                //松弛操作;
                {
                    tmp = mp[i][k] + mp[k][j];
                    if(tmp < mp[i][j])
                    {
                        mp[i][j] = tmp;
                    }
                }
            }
        }
    }
}

算法实现原理

由于我们只需要确定节点对(i,j)之间是存在i->j的路径,所以,对于松弛操作可以有两种优化方式,

(1)将所有节点对之间的存在的直接连通的边权重设为1,不连通设为INF(无穷大)。然后运行该算法,如果mp[i][j] < n;则(i,j)之间存在一条简单路径。如果mp[i][j] = INF,则两者之间不存在路径。

(2)可以将松弛策略改为,mp[i][j] == 1|| (mp[i][k] ==1 && mp[k][j] == 1)也即是要么,i可以通过{1,2,3,,,k-1}中的部分节点到达j,要么i可以通过{1,2,3,,,k-1}中的部分节点到达j,可以参考对Floyd warshall 算法的分析链接

Floyd warshall 传递闭包算法的实现

void floyd_warshall()
{
    for(int k = 1; k <= n; ++k)
    {
        for(int i = 1; i <= n; ++i)
        {
            for(int j = 1; j <= n; ++j)
            {
                if(mp[i][j] == 1 || mp[i][k] == 1 && mp[k][j] == 1)
                {
                    mp[i][j] = 1;
                }
            }
        }
    }
}

时间复杂度

容易知道时间复杂度为O(V^3);

DFS 传递闭包算法

算法分析

DFS时间复杂度为O(V+E);
使用对每个节点进行DFS,每次可以得出一个节点的可以到达的节点,可以求出有向图的传递闭包,时间复杂度为V*O(V+E),即O(V*(V+E));
如果图的边数较少时,第二种算法更有效,可以根据题目的数据约束进行选择。

代码实现

int vis[N][N];//vis[i][j]表示i->j可达
void dfs(int s)//普通的dfs算法
{
    int num = n;
    stack<int> st;
    st.push(s);
    vis[s][s] = 1;
    while(!st.empty())
    {
        int now = st.top();
        st.pop();
        int len = ed[now].size();
        for(int i = 0;i < len; ++i)
        {
            if(vis[s][ed[now][i]] == 0)
            {
                st.push(ed[now][i]);
                vis[s][ed[now][i]] = 1;
            }
        }
    }
}           

例题

Cow Contest

通信网络可以在CCF csp 官网进行提交练习。

如有错误,恳请指正。

原文地址:https://www.cnblogs.com/lif323/p/9353639.html

时间: 2024-10-10 16:46:31

有向图传递闭包的相关文章

hdu - 1704 Rank(简单dfs)

http://acm.hdu.edu.cn/showproblem.php?pid=1704 遇到标记过的就dfs,把隐含的标记,最后计数需要注意. 1 #include <cstdio> 2 #include <cstring> 3 int n; 4 int vis[501][501]; 5 void dfs(int x,int y) 6 { 7 for(int i=1;i<=n;i++) 8 if(vis[y][i]) 9 { 10 vis[x][i]=1; 11 dfs

11.3.4 例题11-4 UVA 247 Calling Circles (有向图的传递闭包)

题目大意: 给你n个人,m条边,a->b,b->a,才能说这两个人是联通的.问现在有多少个联通圈.输出每个联通圈.n<=25 解题思路: 直接建图,用有向图的闭包传递特性来处理每个人之间的联通关系.然后dfs一次,遍历邻接矩阵中与某个点相连的几个点,边遍历, 边打印输出. 代码: # include<cstdio> # include<iostream> # include<map> # include<cstring> # include

UVa 247 - Calling Circles(Floyd求有向图的传递闭包)

链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=183 题意: 如果两个人相互打电话(直接或间接),则说他们在同一个电话圈里.例如,a打给b,b打给c,c打给d,d打给a,则这4个人在同一个圈里:如果e打给f但f不打给e,则不能推出e和f在同一个电话圈里.输入n(n≤25)个人的m次电话,找出所有电话圈.人名只包含字母,不超过25个

POJ-3660.Cow Contest(有向图的传递闭包)

Cow Contest Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 17797   Accepted: 9893 Description N (1 ≤ N ≤ 100) cows, conveniently numbered 1..N, are participating in a programming contest. As we all know, some cows code better than other

Bzoj 1703: [Usaco2007 Mar]Ranking the Cows 奶牛排名 传递闭包,bitset

1703: [Usaco2007 Mar]Ranking the Cows 奶牛排名 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 323  Solved: 238[Submit][Status][Discuss] Description 农夫约翰有N(1≤N≤1000)头奶牛,每一头奶牛都有一个确定的独一无二的正整数产奶率.约翰想要让这些奶牛按产奶率从高到低排序.    约翰已经比较了M(1≤M≤10000)对奶牛的产奶率,但他发现,他还需要再做一

poj2594最小顶点覆盖+传递闭包

传递闭包最开始是在Floyd-Warshall算法里面出现的,当时这算法用的很少就被我忽视了.. 传递闭包是指如果i能到达k,并且k能到达j,那么i就能到达j Have you ever read any book about treasure exploration? Have you ever see any film about treasure exploration? Have you ever explored treasure? If you never have such exp

传递闭包

传递闭包: 有向图的传递闭包表示的就是两个顶点之间的可达性 将有向图化为布尔矩阵,两点有边相连为 1,否则为 0 布尔矩阵 B 自乘 N 次,进行布尔运算得到B(N) B(N)[i][j]意义是,能否经过 N 长度的路径从 i --> j 而将中间过程的产生的一系列 B 经行布尔运算叠加得到的最后矩阵 M 就是该图中的任意两点是否可达的信息,即M[i][j] == 1,则意味着 i --> j 可达 import numpy A0 = numpy.array( [ [False, True,

十六、图算法之有向图

有向图 有向图的数据结构 采用链表 public class Digraph { private static final String NEWLINE = System.getProperty("line.separator"); private final int V; // number of vertices in this digraph private int E; // number of edges in this digraph private Bag<Inte

Treasure Exploration---poj2594(传递闭包+最大匹配)

题目链接:http://poj.org/problem?id=2594 在外星上有n个点需要机器人去探险,有m条单向路径.问至少需要几个机器人才能遍历完所有的点,一个点可以被多个机器人经过. 因为图是一个有向图 例如 1—>3, 2—>3; 3—>4; 3—>5; 左边是floyd之前的,右边是传递之后的,左边的最大匹配是2,右边是3: 其中为什么用传递闭包就能求最大匹配,自己只可意会不可言传:—_—; #include<stdio.h> #include<str