2023-05-12:存在一个由 n 个节点组成的无向连通图,图中的节点按从 0 到 n - 1 编号, 给你一个数组 graph 表示这个图, 其中,graph[i] 是一个列表,由所有与节点 i

这篇具有很好参考价值的文章主要介绍了2023-05-12:存在一个由 n 个节点组成的无向连通图,图中的节点按从 0 到 n - 1 编号, 给你一个数组 graph 表示这个图, 其中,graph[i] 是一个列表,由所有与节点 i。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

2023-05-12:存在一个由 n 个节点组成的无向连通图,图中的节点按从 0 到 n - 1 编号,
给你一个数组 graph 表示这个图,
其中,graph[i] 是一个列表,由所有与节点 i 直接相连的节点组成。
返回能够访问所有节点的最短路径的长度。
你可以在任一节点开始和停止,也可以多次重访节点,并且可以重用边。
输入:graph = [[1,2,3],[0],[0],[0]]。
输出:4。

答案2023-05-12:

大体步骤如下:

1.首先,在 main 函数中调用 shortestPathLength 函数,并将图的邻接表 graph 作为参数传入。

2.在 shortestPathLength 函数中,获取图中节点的个数 n,使用 Floyd 算法计算所有节点之间的最短路径距离,并将结果保存到 distance 二维数组中,同时初始化一个 ans 变量为整型最大值。

3.接下来,初始化一个 dp 数组,其中 dp[i][j] 表示当前状态为 i(二进制表示),当前在节点 j 的情况下,能形成的最短路径长度。同时,对于 dp 数组进行初始化,将所有元素的值设为 -1。

4.循环遍历每个节点 i,从 i 节点出发,通过 process 函数求出访问所有节点的最短路径长度,并更新 ans 的值。

5.在 process 函数中,首先判断当前状态是否已经访问了所有节点,如果是,返回 0 表示已经完成访问。如果 dp 数组中已有对应状态和当前节点的最短路径长度,则直接返回该值,避免重复计算。

6 如果上述条件都不满足,则遍历所有未访问过的且与当前节点 cur 相邻的节点 next,对于这些节点,递归调用 process 函数,并记录访问当前节点 cur 和下一个节点 next 所需的距离 distance[cur][next],然后将其加上递归得到的 nextAns 值,更新 ans 的值。

7.最后,将计算出的最短路径长度 ans 保存到 dp 数组中,并返回该值。在主函数中输出 ans 的值即为能够访问所有节点的最短路径的长度。

时间复杂度:本算法中使用了 Floyd 算法计算所有节点之间的最短路径,其时间复杂度为 O(n^3);同时,使用动态规划求解当前状态下访问所有节点的最短路径长度,需要遍历状态空间和邻接表,时间复杂度为 O(2^n * n^2)。因此,总的时间复杂度为 O(n^3 + 2^n * n^2)。

空间复杂度:本算法中使用了一个距离矩阵 distance 数组来存储节点之间的最短路径距离,其空间复杂度为 O(n^2);同时,使用了一个 dp 数组来记录状态和节点的最短路径长度,其空间复杂度也是 O(2^n * n)。因此,总的空间复杂度为 O(n^2 + 2^n * n)。

go语言完整代码如下:

package main

import (
	"fmt"
	"math"
)

func shortestPathLength(graph [][]int) int {
	n := len(graph)
	distance := floyd(n, graph)
	ans := math.MaxInt32
	dp := make([][]int, 1<<n)
	for i := 0; i < (1 << n); i++ {
		dp[i] = make([]int, n)
		for j := 0; j < n; j++ {
			dp[i][j] = -1
		}
	}
	for i := 0; i < n; i++ {
		ans = min(ans, process(1<<i, i, n, distance, dp))
	}
	return ans
}

func floyd(n int, graph [][]int) [][]int {
	distance := make([][]int, n)
	for i := 0; i < n; i++ {
		distance[i] = make([]int, n)
		for j := 0; j < n; j++ {
			distance[i][j] = math.MaxInt32
		}
	}
	for i := 0; i < n; i++ {
		distance[i][i] = 0
	}
	for cur := 0; cur < n; cur++ {
		for _, next := range graph[cur] {
			distance[cur][next] = 1
			distance[next][cur] = 1
		}
	}
	for jump := 0; jump < n; jump++ {
		for from := 0; from < n; from++ {
			for to := 0; to < n; to++ {
				if distance[from][jump] != math.MaxInt32 && distance[jump][to] != math.MaxInt32 &&
					distance[from][to] > distance[from][jump]+distance[jump][to] {
					distance[from][to] = distance[from][jump] + distance[jump][to]
				}
			}
		}
	}
	return distance
}

func process(status, cur, n int, distance, dp [][]int) int {
	if status == (1<<n)-1 {
		return 0
	}
	if dp[status][cur] != -1 {
		return dp[status][cur]
	}
	ans := math.MaxInt32
	for next := 0; next < n; next++ {
		if status&(1<<next) == 0 && distance[cur][next] != math.MaxInt32 {
			nextAns := process(status|(1<<next), next, n, distance, dp)
			if nextAns != math.MaxInt32 {
				ans = min(ans, distance[cur][next]+nextAns)
			}
		}
	}
	dp[status][cur] = ans
	return ans
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func main() {
	graph := [][]int{{1, 2, 3}, {0}, {0}, {0}}
	ans := shortestPathLength(graph)
	fmt.Println(ans)
}

2023-05-12:存在一个由 n 个节点组成的无向连通图,图中的节点按从 0 到 n - 1 编号, 给你一个数组 graph 表示这个图, 其中,graph[i] 是一个列表,由所有与节点 i

rust语言完整代码如下:

fn shortest_path_length(graph: Vec<Vec<i32>>) -> i32 {
    let n = graph.len();
    let distance = floyd(n, &graph);
    let mut ans = std::i32::MAX;
    let mut dp = vec![vec![-1; n]; 1 << n];
    for i in 0..(1 << n) {
        for j in 0..n {
            dp[i][j] = -1;
        }
    }
    for i in 0..n {
        ans = ans.min(process(1 << i, i, n, &distance, &mut dp));
    }
    return ans;
}

fn floyd(n: usize, graph: &Vec<Vec<i32>>) -> Vec<Vec<i32>> {
    let mut distance = vec![vec![std::i32::MAX; n]; n];
    // 初始化认为都没路
    for i in 0..n {
        for j in 0..n {
            distance[i][j] = std::i32::MAX;
        }
    }
    // 自己到自己的距离为0
    for i in 0..n {
        distance[i][i] = 0;
    }
    // 支持任意有向图,把直接边先填入
    for cur in 0..n {
        for &next in graph[cur].iter() {
            distance[cur][next as usize] = 1;
            distance[next as usize][cur] = 1;
        }
    }
    // O(N^3)的过程
    // 枚举每个跳板
    // 注意! 跳板要最先枚举,然后是from和to
    for jump in 0..n {
        for from in 0..n {
            for to in 0..n {
                if distance[from][jump] != std::i32::MAX
                    && distance[jump][to] != std::i32::MAX
                    && distance[from][to] > distance[from][jump] + distance[jump][to]
                {
                    distance[from][to] = distance[from][jump] + distance[jump][to];
                }
            }
        }
    }
    return distance;
}

// status : 所有已经走过点的状态
// 0 1 2 3 4 5
// int
//        5 4 3 2 1 0
//        0 0 1 1 0 1
// cur : 当前所在哪个城市!
// n : 一共有几座城
// 返回值 : 从此时开始,逛掉所有的城市,至少还要走的路,返回!
fn process(
    status: i32,
    cur: usize,
    n: usize,
    distance: &Vec<Vec<i32>>,
    dp: &mut Vec<Vec<i32>>,
) -> i32 {
    // 5 4 3 2 1 0
    // 1 1 1 1 1 1
    // 1 << 6 - 1
    if status == (1 << n) - 1 {
        return 0;
    }
    if dp[status as usize][cur] != -1 {
        return dp[status as usize][cur];
    }
    let mut ans = std::i32::MAX;
    // status:
    // 5 4 3 2 1 0
    // 0 0 1 0 1 1
    // cur : 0
    // next : 2 4 5
    for next in 0..n {
        if (status & (1 << next)) == 0 && distance[cur][next] != std::i32::MAX {
            let next_ans = process(status | (1 << next), next, n, distance, dp);
            if next_ans != std::i32::MAX {
                ans = ans.min(distance[cur][next] + next_ans);
            }
        }
    }
    dp[status as usize][cur] = ans;
    return ans;
}

fn main() {
    let graph = vec![vec![1, 2, 3], vec![0], vec![0], vec![0]];
    let ans = shortest_path_length(graph);
    println!("{}", ans);
}

2023-05-12:存在一个由 n 个节点组成的无向连通图,图中的节点按从 0 到 n - 1 编号, 给你一个数组 graph 表示这个图, 其中,graph[i] 是一个列表,由所有与节点 i

c语言完整代码如下:


#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 15, INF = 0x3f3f3f3f;

int n;
int dist[N][N], dp[1 << N][N];

int floyd(vector<vector<int>>& graph)
{
    n = graph.size();
    memset(dist, 0x3f, sizeof dist);

    for (int i = 0; i < n; i++)
        for (auto j : graph[i])
            dist[i][j] = 1;

    for (int k = 0; k < n; k++)
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);

    return 0;
}

int dfs(int status, int cur)
{
    if (status == (1 << n) - 1)
        return 0;

    if (dp[status][cur] != -1)
        return dp[status][cur];

    int ans = INF;

    for (int next = 0; next < n; next++)
        if ((status & (1 << next)) == 0 && dist[cur][next] != INF)
        {
            int nextAns = dfs(status | (1 << next), next);
            if (nextAns != INF)
                ans = min(ans, dist[cur][next] + nextAns);
        }

    return dp[status][cur] = ans;
}

int shortestPathLength(vector<vector<int>>& graph) {
    memset(dp, -1, sizeof dp);
    floyd(graph);

    int ans = INF;
    for (int i = 0; i < n; i++)
        ans = min(ans, dfs(1 << i, i));
    return ans;
}

int main()
{
    vector<vector<int>> graph = { {1,2,3},{0},{0},{0} };
    cout << shortestPathLength(graph) << endl;

    return 0;
}

2023-05-12:存在一个由 n 个节点组成的无向连通图,图中的节点按从 0 到 n - 1 编号, 给你一个数组 graph 表示这个图, 其中,graph[i] 是一个列表,由所有与节点 i

c++语言完整代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define N 15
#define INF 0x3f3f3f3f

int n;
int dist[N][N], dp[1 << N][N];

void floyd(int** graph, int graphSize, int* graphColSize)
{
    n = graphSize;
    memset(dist, 0x3f, sizeof dist);

    for (int i = 0; i < n; i++)
        for (int j = 0; j < graphColSize[i]; j++)
            dist[i][graph[i][j]] = 1;

    for (int k = 0; k < n; k++)
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                dist[i][j] = dist[i][j] < dist[i][k] + dist[k][j] ? dist[i][j] : dist[i][k] + dist[k][j];
}

int dfs(int status, int cur)
{
    if (status == (1 << n) - 1)
        return 0;

    if (dp[status][cur] != -1)
        return dp[status][cur];

    int ans = INF;

    for (int next = 0; next < n; next++)
        if ((status & (1 << next)) == 0 && dist[cur][next] != INF)
        {
            int nextAns = dfs(status | (1 << next), next);
            if (nextAns != INF)
                ans = ans < dist[cur][next] + nextAns ? ans : dist[cur][next] + nextAns;
        }

    return dp[status][cur] = ans;
}

int shortestPathLength(int** graph, int graphSize, int* graphColSize) {
    memset(dp, -1, sizeof dp);
    floyd(graph, graphSize, graphColSize);

    int ans = INF;
    for (int i = 0; i < n; i++)
        ans = ans < dfs(1 << i, i) ? ans : dfs(1 << i, i);
    return ans;
}

int main()
{
    int graphSize = 4;
    int graphColSize[] = { 3, 1, 1, 1 };
    int** graph = (int**)malloc(sizeof(int*) * graphSize);
    for (int i = 0; i < graphSize; i++)
    {
        graph[i] = (int*)malloc(sizeof(int) * graphColSize[i]);
        memcpy(graph[i], (int[]) { 0 }, sizeof(int)* graphColSize[i]);
    }
    graph[0][0] = 1;
    graph[0][1] = 2;
    graph[0][2] = 3;

    printf("%d\n", shortestPathLength(graph, graphSize, graphColSize));

    for (int i = 0; i < graphSize; i++)
        free(graph[i]);
    free(graph);

    return 0;
}

2023-05-12:存在一个由 n 个节点组成的无向连通图,图中的节点按从 0 到 n - 1 编号, 给你一个数组 graph 表示这个图, 其中,graph[i] 是一个列表,由所有与节点 i文章来源地址https://www.toymoban.com/news/detail-441245.html

到了这里,关于2023-05-12:存在一个由 n 个节点组成的无向连通图,图中的节点按从 0 到 n - 1 编号, 给你一个数组 graph 表示这个图, 其中,graph[i] 是一个列表,由所有与节点 i的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 2023-06-10:给定一个由 n 个节点组成的网络,用 n x n 个邻接矩阵 graph 表示 在节点网络中,只有当 graph[i][j] = 1 时,节点 i 能够直接连接到另一个节点 j。

    2023-06-10:给定一个由 n 个节点组成的网络,用 n x n 个邻接矩阵 graph 表示 在节点网络中,只有当 graph[i][j] = 1 时,节点 i 能够直接连接到另一个节点 j。 一些节点 initial 最初被恶意软件感染。只要两个节点直接连接, 且其中至少一个节点受到恶意软件的感染,那么两个节点都

    2024年02月08日
    浏览(30)
  • LeetCode:1402. 做菜顺序、2316. 统计无向图中无法互相到达点对数

    1. 1402 做菜顺序 题目详细为: 一个厨师收集了他 n 道菜的满意程度 satisfaction ,这个厨师做出每道菜的时间都是 1 单位时间。 一道菜的 「 like-time 系数 」定义为烹饪这道菜结束的时间(包含之前每道菜所花费的时间)乘以这道菜的满意程度,也就是 time[i]*satisfaction[i] 。 返回

    2024年01月23日
    浏览(26)
  • 【学习笔记】无向图的连通性

    定义: 在无向图连通图中,若把点 (x) 删去后整个图就不连通了,则 (x) 为割点(割顶)。 朴素方法: 每次删去一个点,然后判断图是否连通,时间复杂度为 (O(n(n+m))) 。 Tarjan 算法: (dfn_x) : (x) 被 dfs 到的时间戳 (low_x) :在 (x) 及以后被搜索的所有节点的 (low) 值

    2024年02月15日
    浏览(31)
  • 【图论】无向图连通性(tarjan算法)

    1. 连通 : 在图论中,连通性是指一个无向图中的任意两个顶点之间存在路径。如果对于图中的任意两个顶点 u 和 v,存在一条路径从 u 到 v,那么图被称为连通图。如果图不是连通的,那么它可以被分为多个 连通分量 ,每个连通分量都是一个连通子图。 2.割点: 割点(Cut V

    2024年02月13日
    浏览(31)
  • 2023-05-17 LeetCode每日一题(判断两个事件是否存在冲突)

    点击跳转到题目位置 给你两个字符串数组 event1 和 event2 ,表示发生在同一天的两个闭区间时间段事件,其中: event1 = [startTime1, endTime1] 且 event2 = [startTime2, endTime2] 事件的时间为有效的 24 小时制且按 HH:MM 格式给出。 当两个事件存在某个非空的交集时(即,某些时刻是两个事

    2024年02月05日
    浏览(41)
  • 一图搞清楚(非)(强)连通图中的极大(小)(强)连通子图

    在学习图的过程中,常常搞不清楚下面这些概念: 连通图、非连通图、强连通图、非强连通图、极大连通子图与连通分量、极大强连通子图与强连通分量、极小连通子图与生成树、极小强连通子图(后面得知根本就没有这个概念)...... 现在决定用一张图(放大查看)对他们

    2024年02月04日
    浏览(29)
  • 求无向连通图的最小生成树 ← Prim算法

    【题目描述】 给定一个 n 个点 m 条边的 无向连通图 。图中可能存在 重边 和 自环 ,边权可能为 负数 。 利用Prim算法求此种无向连通图的最小生成树的树边权重之和。 【输入格式】 第一行包含两个整数 n 和 m。 接下来 m 行,每行包含三个整数 u,v,w,表示点 u 和点 v 之

    2024年02月07日
    浏览(37)
  • 创建一个区块链,是由三个节点组成的去中心化网络。

    目录 一、准备工作: 1、创建三个python文件: 2、创建nodes.json文件 3、transaction.json文件 4、打开三个控制台 二、在三个节点上进行交互。 二、添加交易发布请求(a向b发送10000coin) lancoin_node_5001.py、lancoin_node_5002.py、lancoin_node_5003.py。 它们每个都将连接到不同的端口,一个端

    2024年04月29日
    浏览(41)
  • CF Round 479 (Div. 3)--E. Cyclic Components(DFS求无向图中独立环的个数)

    You are given an undirected graph consisting of n vertices and m edges. Your task is to find the number of connected components which are cycles. Here are some definitions of graph theory. An undirected graph consists of two sets: set of nodes (called vertices) and set of edges. Each edge connects a pair of vertices. All edges are bidirectional (i.e. if

    2024年02月09日
    浏览(24)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包