题目详情

给出一个无向图,判断其是欧拉、半欧拉还是非欧拉图。

  • 欧拉图:可以构成欧拉回路
  • 半欧拉图:可以构成欧拉通路
  • 非欧拉图:啥也不行

我的版本

没撕出来……卡死在判断通路上了。

  1. import java.util.*;
  2. import java.io.*;
  3. public class Main {
  4. public static void main(String[] args) throws IOException {
  5. BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  6. String[] line = br.readLine().split(" ");
  7. int n = Integer.parseInt(line[0]) + 1; // 点数,点索引从1开始
  8. int m = Integer.parseInt(line[1]); // 边数
  9. int[][] eds = new int[n][n];
  10. HashMap<Integer, Integer> hm = new HashMap<>();
  11. for (int i = 0; i < m; i ++) {
  12. line = br.readLine().split(" ");
  13. int x = Integer.parseInt(line[0]);
  14. int y = Integer.parseInt(line[1]);
  15. eds[x][y] = eds[y][x] = 1; // 无向图
  16. int count;
  17. count = hm.computeIfAbsent(x, k->0);
  18. hm.put(x, count+1);
  19. count = hm.computeIfAbsent(y, k->0);
  20. hm.put(y, count+1);
  21. }
  22. for (int i = 1; i < n; i ++) {
  23. if (i == 1) System.out.print(hm.get(i));
  24. else System.out.print(" "+hm.get(i));
  25. }
  26. System.out.println();
  27. int isPrint = 0;
  28. for (int k = 1; k < n; k ++) {
  29. // 从索引为1的点开始,最终可以到达所有的点,使用栈记录到过的点
  30. int[] bool = new int[n];
  31. Stack<Integer> st = new Stack<>();
  32. st.add(k);
  33. bool[k] = 1;
  34. while (st.size() != 0 && st.size() < n - 1) {
  35. int node = st.peek();
  36. int b = 0;
  37. for (int i = 1; i < n; i++) {
  38. if (bool[i] == 0 && eds[node][i] == k) {
  39. st.add(i);
  40. b = 1;
  41. break;
  42. }
  43. }
  44. if (b == 0) {
  45. st.pop();
  46. if (st.size() != 0) eds[st.peek()][node] = k+1;
  47. } else {
  48. bool[node] = 1;
  49. }
  50. if (st.size() == 0) {
  51. System.out.println("Non-Eulerian");
  52. isPrint = 1;
  53. } else if (st.size() == n - 1 && eds[st.peek()][1] == k) {
  54. System.out.println("Eulerian");
  55. isPrint = 1;
  56. }
  57. }
  58. }
  59. if (isPrint == 0) {
  60. System.out.println("Semi-Eulerian");
  61. }
  62. }
  63. }

看了答案的版本

其实欧拉图是有规律的,学的离散喂狗了……欧拉图/半欧拉图首先是连通图(使用栈判断),在此基础上,

  • 欧拉图:所有的点的度为偶数
  • 半欧拉:只有两个点的度为奇数
  • 非欧拉:其他

手撕的这个版本有一个节点超时了。

  1. import java.util.*;
  2. import java.io.*;
  3. public class Main {
  4. public static void main(String[] args) throws IOException {
  5. BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  6. String[] line = br.readLine().split(" ");
  7. int n = Integer.parseInt(line[0]) + 1; // 点数,点索引从1开始
  8. int m = Integer.parseInt(line[1]); // 边数
  9. int[][] eds = new int[n][n];
  10. int[] hm = new int[n];
  11. for (int i = 0; i < m; i ++) {
  12. line = br.readLine().split(" ");
  13. int x = Integer.parseInt(line[0]);
  14. int y = Integer.parseInt(line[1]);
  15. eds[x][y] = eds[y][x] = 1; // 无向图
  16. hm[x] += 1;
  17. hm[y] += 1;
  18. }
  19. int[] bool = new int[n];
  20. Stack<Integer> st = new Stack<>();
  21. st.add(1);
  22. while (st.size() != 0) {
  23. int node = st.peek();
  24. bool[node] = 1;
  25. int b = 0;
  26. for (int i = 1; i < n; i++) {
  27. if (bool[i] == 0 && eds[node][i] == 1) {
  28. st.add(i);
  29. b = 1;
  30. break;
  31. }
  32. }
  33. if (b == 0) st.pop();
  34. }
  35. int oddNum = 0; // 奇度节点数目
  36. int isConnect = 1; // 是否连通
  37. for (int i = 1; i < n; i ++) {
  38. if (hm[i] % 2 != 0) oddNum ++;
  39. if (bool[i] == 0) isConnect = 0;
  40. if (i == 1) System.out.print(hm[i]);
  41. else System.out.print(" "+hm[i]);
  42. }
  43. System.out.println();
  44. if (oddNum == 0 && isConnect == 1) System.out.println("Eulerian");
  45. else if (oddNum == 2 && isConnect == 1) System.out.println("Semi-Eulerian");
  46. else System.out.println("Non-Eulerian");
  47. }
  48. }