【搜索】C_UVa 20_Firetruck(dfs + uf)

一、Problem

The Center City fire department collaborates with the transportation department to maintain mapsof the city which reflects the current status of the city streets.

On any given day, several streets areclosed for repairs or construction. Firefighters need to be able to select routes from the firestations tofires that do not use closed streets.Central City is divided into non-overlapping fire districts, each containing a single firestation. Whena fire is reported, a central dispatcher alerts the firestation of the district where the fire is located andgives a list of possible routes from the firestation to the fire. You must write a program that the centraldispatcher can use to generate routes from the district firestations to the fires.

Input:

The city has a separate map for each fire district. Streetcorners of each map are identified by positiveintegers less than 21, with the firestation always on corner #1. The input file contains several test casesrepresenting different fires in different districts.

The first line of a test case consists of a single integer which is the number of the streetcorner closest to the fire.

The next several lines consist of pairs of positive integers separated by blanks which are the adjacent streetcorners of open streets. (For example, if the pair 4 7 is on a line in the file, then the street between streetcorners 4 and 7 is open. There are no other streetcorners between 4 and7 on that section of the street.)

The final line of each test case consists of a pair of 0’s.

Output:

For each test case, your output must identify the case by number (‘CASE 1:’, ‘CASE 2:’, etc). It mustlist each route on a separate line, with the streetcorners written in the order in which they appear onthe route. And it must give the total number routes from firestation to the fire. Include only routeswhich do not pass through any streetcorner more than once. (For obvious reasons, the firedepartment doesn’t want its trucks driving around in circles.)Output from separate cases must appear on separate lines.

Sample Input:
6
1 2
1 3
3 4
3 5
4 6
5 6
2 3
2 4
0 0
4
2 3
3 4
5 1
1 6
7 8
8 9
2 5
5 7
3 1
1 8
4 6
6 9
0 0

CASE 1:
1 2 3 4 6
1 2 3 5 6
1 2 4 3 5 6
1 2 4 6
1 3 2 4 6
1 3 4 6
1 3 5 6
There are 7 routes from the firestation to streetcorner 6.

CASE 2:
1 3 2 5 7 8 9 6 4
1 3 4
1 5 2 3 4
1 5 7 8 9 6 4
1 6 4
1 6 9 8 7 5 2 3 4
1 8 7 5 2 3 4
1 8 9 6 4
There are 8 routes from the firestation to streetcorner 4.

https://www.luogu.com.cn/problem/UVA208

二、Solution

方法一:dfs

服了…用结构体+数组存图遍历得到路径是非字典序的?

import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
	static class Solution {
		int[] h;
		List<Integer> path;
		Edge[] e;
		int tot, E, MAXN = 20 + 5;
		boolean[] vis;
		void add(int u, int v) {
			e[++tot] = new Edge();
			e[tot].to = v;
			e[tot].next = h[u];
			h[u] = tot;
		}
		void dfs(int s) {
			if (s == E) {
			    for (int i = 0; i < path.size(); i++) 
			        System.out.print(path.get(i) + " ");
		        System.out.println();
				return;
			}
			for (int i = h[s]; i != 0; i = e[i].next) {
			    int to = e[i].to;
			    if  (!vis[to]) {
		        	path.add(to);
			        vis[to] = true;
    				dfs(to);
    				vis[to] = false;
    				path.remove(path.size()-1);
			    }
			}
		}
		void init() {
			Scanner sc = new Scanner(new BufferedInputStream(System.in));
			while (sc.hasNext()) {
			    path = new ArrayList<>();
    			h = new int[MAXN];
    			e = new Edge[MAXN*2];
    			vis = new boolean[MAXN];
				E = sc.nextInt();
				while (sc.hasNext()) {
					int a = sc.nextInt(), b = sc.nextInt();
					if (a == 0 && b == 0)
						break;
					add(a, b);
			        add(b, a);
				}
				vis[1] = true;
				path.add(1);
				dfs(1);
			}
		}
		class Edge{
			int to, next;
			Edge() {}
		}
	}
    public static void main(String[] args) throws IOException {  
        Solution s = new Solution();
		s.init();
    }
}

用二维数组存…\

import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
	static class Solution {
		List<Integer> path;
		int[][] g;
		int cnt, E, MAXN = 20 + 5;
		boolean[] vis;
		int tot;
		void dfs(int s, int cnt, int[] p) {
			if (s == E) {
			    for (int i = 0; i < cnt; i++) 
			        System.out.print(p[i] + " ");
		        System.out.println();
				tot++;
				return;
			}
			for (int i = 2; i < MAXN; i++) {
				if (g[s][i] > 0 && !vis[i]) {
					vis[i] = true;
					p[cnt] = i;
					dfs(i, cnt+1, p);
					vis[i] = false;
				}
			}
		}
		void init() {
			Scanner sc = new Scanner(new BufferedInputStream(System.in));
			int c = 1;
			while (sc.hasNext()) {
				System.out.printf("CASE %d:\n", c++);
    			vis = new boolean[MAXN];
				E = sc.nextInt();
				g = new int[MAXN][MAXN];
				int[] p = new int[MAXN];
				while (true) {
					int a = sc.nextInt(), b = sc.nextInt();
					if (a == 0 && b == 0)
						break;
					g[a][b] = g[b][a] = 1;
				}
    			vis[1] = true;
    			p[0] = 1;
    			dfs(1, 1, p);
				System.out.printf("There are %d routes from the firestation to streetcorner %d.\n", tot, E);
				tot = 0;
			}
		}
	}
    public static void main(String[] args) throws IOException {  
        Solution s = new Solution();
		s.init();
    }
}

超时了…样例是保证了结点 1 和结点 E 是连通的,但其他测试数据并不保证…所以需要先证明图的连通性…

import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
	static class Solution {
		List<Integer> path;
		int[][] g;
		int cnt, E, MAXN = 20 + 5;
		boolean[] vis;
		int tot;
		void dfs(int s, int cnt, int[] p) {
			if (s == E) {
			    for (int i = 0; i < cnt; i++) 
			        System.out.print(p[i] + " ");
		        System.out.println();
				tot++;
				return;
			}
			for (int i = 2; i < MAXN; i++) {
				if (g[s][i] > 0 && !vis[i]) {
					vis[i] = true;
					p[cnt] = i;
					dfs(i, cnt+1, p);
					vis[i] = false;
				}
			}
		}
		void init() {
			Scanner sc = new Scanner(new BufferedInputStream(System.in));
			int c = 1;
			while (sc.hasNext()) {
				System.out.printf("CASE %d:\n", c++);
    			vis = new boolean[MAXN];
				E = sc.nextInt();
				g = new int[MAXN][MAXN];
				UF uf = new UF(MAXN);
				int[] p = new int[MAXN];
				while (true) {
					int a = sc.nextInt(), b = sc.nextInt();
					if (a == 0 && b == 0)
						break;
					g[a][b] = g[b][a] = 1;
					uf.union(a, b);
					
				}
				if (!uf.isConn(1, E)) {
					System.out.printf("There are 0 routes from the firestation to streetcorner %d.\n", E);
					continue;
				}
    			vis[1] = true;
    			p[0] = 1;
    			dfs(1, 1, p);
				System.out.printf("There are %d routes from the firestation to streetcorner %d.\n", tot, E);
				tot = 0;
			}
		}
		class UF {
			int[] id;
			UF(int N) {
				id = new int[N+1];
				for (int i = 1; i <= N; i++) {
					id[i] = i;
				}
			}
			int find(int p) {
				while (p != id[p]) {
					id[p] = id[id[p]];
					p = id[p];
				}
				return p;
			}
			boolean isConn(int p, int q) {
				return find(p) == find(q);
			}
			void union(int p, int q) {
				int pID = find(p), qID = find(q);
				if (pID == qID)
					return;
				id[pID] = qID;
			}
		}
	}
    public static void main(String[] args) throws IOException {  
        Solution s = new Solution();
		s.init();
    }
}

复杂度分析

  • 时间复杂度: O ( . . . ) O(...)
  • 空间复杂度: O ( . . . ) O(...)
原创文章 787 获赞 314 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_43539599/article/details/105865353