赞
踩
迪杰斯特拉算法采用贪心的策略,集合T{}用来存放当前已找到的最短路径节点集合。将起始点的路径权重赋
为0,当前节点不能到达的节点权重赋为无穷大。
下面展示的是无向带权值图求最短路径:
具体步骤:
每次添加路径最小值的节点到T
集合。
结合图理解:
邻接表结构:链表头结点存放的是下标。
题目:一共有n个点,m条无向边,每条边都有长度d和花费p,给定起点s终点t,要求输出起点到终点的最短距离
及其花费,如果最短距离有多条路线,则输出花费最少的。
输出:最小距离和花费。
创建Vertex类,构建邻接表:
class Edge { // 存放边的信息,next表示下一个节点,dist表示长度,cost表示花费 int next; int dist; int cost; public Edge(int next, int dist, int cost) { this.next = next; this.dist = dist; this.cost = cost; } } class Vertex { int num; ArrayList<Edge> edge; // 使用链表结构存储 public Vertex(int num) { this.num = num; this.edge = new ArrayList<Edge>(); } }
ACM模式:
Scanner in = new Scanner(System.in); while (in.hasNext()) { int n = in.nextInt(); // 点数 int m = in.nextInt(); // 边数 if (m == 0) break; Vertex[] list = new Vertex[n + 1]; // 初始化Vertex for (int i = 1; i <= n; i++){ list[i] = new Vertex(i); } for (int i = 0; i < m; i++) { int a = in.nextInt(); int b = in.nextInt(); int dist = in.nextInt(); // 长度 int cost = in.nextInt(); // 花费 list[a].edge.add(new Edge(b, dist, cost)); // a->b 的长度和花费 list[b].edge.add(new Edge(a, dist, cost)); } int s = in.nextInt(); // 起点 int t = in.nextInt(); // 终点 boolean[] marked = new boolean[n + 1]; // 用来记录当前节点是否更新 int[] cost = new int[n + 1]; int[] dist = new int[n + 1]; for (int i = 1; i <= n; i++) { cost[i] = Integer.MAX_VALUE; // 初始花费设为max dist[i] = -1; // 不可达用-1表示 marked[i] = false; } dist[s] = 0; cost[s] = 0; marked[s] = true; int p = s; // 当前起点p // Dijkstra for(int i=1;i<=n;i++){ for(int j=0;j<list[p].edge.size();j++){ int next = list[p].edge.get(j).next; int c = list[p].edge.get(j).cost; int d = list[p].edge.get(j).dist; if(marked[next]==true) continue; // 三种情况进行更新:距离未更新时、距离需更新时、距离相等花费变小时 if(dist[next]==-1 || dist[next]>dist[p]+d || dist[next]== dist[p]+d && cost[next]>cost[p]+c){ dist[next] = dist[p] + d; cost[next] = cost[p] + c; } } int min = Integer.MAX_VALUE; for(int j=1;j<=n;j++){ if(marked[j]==true) continue; if(dist[j]==-1) continue; if(dist[j]<min){ min = dist[j]; p = j; } } marked[p] = true; } System.out.printf("%d %d\n", dist[t],cost[t]);
广度优先搜索算法(BFS),是一种利用队列实现的搜索算法。
深度优先搜索算法(DFS),是一种利用递归实现的搜索算法。
题目:给定n个节点,节点从0依次编号,0固定为根节点,若节点设置障碍则不可达,输出从根节点到叶子结点的 路径(只有一条边相连的为叶子结点),否则输出NULL。 输入: 第一行 n 【节点数】 第二行 m 【边数】 接下来m行 x y 【x与y相连】 第m+3行 b 【接下来有b个障碍物节点】 接下来b行 k 【节点k有障碍物】 例: 7 6 0 1 0 3 1 2 3 4 1 5 5 6 1 4
因为使用邻接表结构存储相邻节点,不要求是二叉树,为了方便画成树的形状。
同样的创建Vertex类,构建邻接表:
class Edge {
int next;
public Edge(int next) {
this.next = next;
}
}
class Vertex {
int num;
ArrayList<Edge> edge;
public Vertex(int num) {
this.num = num;
this.edge = new ArrayList<Edge>();
}
}
bfs
public static int bfs(int x, Vertex[] list, int[] book, int[] child){ Queue<Integer> queue = new LinkedList<>(); queue.offer(x); while (!queue.isEmpty()){ int top = queue.poll(); int size = list[top].edge.size(); // 相连的边的个数 if (size == 0){ return top; }else{ for (int i = 0; i < size; i++) { int next = list[top].edge.get(i).next; if (book[next] == 1) continue; queue.offer(next); child[next] = top; } } } return -1; }
Scanner scan = new Scanner(System.in); while (scan.hasNext()) { int n = scan.nextInt(); int m = scan.nextInt(); int[] child = new int[n]; Arrays.fill(child, -1); Vertex[] list = new Vertex[n]; for (int i = 0; i < n; i++) list[i] = new Vertex(i); for (int i = 0; i < m; i++) { int a = scan.nextInt(); int b = scan.nextInt(); list[a].edge.add(new Edge(b)); // 单向 } int block_num = scan.nextInt(); int[] book = new int[n]; for (int i = 0; i < block_num; i++) { int z = scan.nextInt(); book[z] = 1; } int ans = bfs(0, list, book, child); if (ans == -1) { System.out.println("NULL"); } else { Deque<Integer> res = new LinkedList<>(); while (ans != -1) { res.addFirst(ans); ans = child[ans]; } while (!res.isEmpty()) { System.out.print(res.poll() + " "); } } }
例:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。