一、题目
二、解题思路
)
http://5b0988e595225.cdn.sohucs.com/images/20171101/f1f45fe9ca37425ba200180be89624b2.gif
http://5b0988e595225.cdn.sohucs.com/images/20171101/a85c0716fcc847f1915dddfcfd019c01.gif
1、如何将黑白点化作图:
创建一个结构体
黑白点都看作顶点,只通过color进行区别
2、如何求对应邻接矩阵:
对储存所有顶点的结构体数组做两次循环,若满足题目中黑点xy坐标大于白点,即将邻接矩阵该位置置为1。
3、具体流程演示:
三、代码(DFS BFS两种实现方法)
1 public class MaxMatching {// 基于DFS 2 3 static int graph[][]; // 邻接表 默认全为0 4 static int n; // 节点数 5 static int visit[]; // 是否访问 6 static int matched[]; // 是否已经匹配,对应的匹配点 7 static vertex V[];//// 结构体数组储存所有黑白 8 9 public class vertex {// 顶点结构体 10 public int color;// 白:0 黑:1 11 public double Vx; 12 public double Vy; 13 } 14 15 public void Init() { 16 System.out.println("输入的黑白点总数为:"); 17 Scanner sc = new Scanner(System.in); 18 n = sc.nextInt(); 19 graph = new int[n][n]; // 邻接表 默认全为0 20 visit = new int[n]; // 是否访问 21 matched = new int[n]; // 是否已经匹配,对应的匹配点 22 V = new vertex[n]; 23 InitGraph();// 初始邻接矩阵 24 } 25 26 private void InitGraph() { 27 Scanner sc = new Scanner(System.in); 28 for (int i = 0; i < n; i++) {// 输入黑白点 29 V[i] = new vertex(); 30 System.out.println("please int color/x/y"); 31 V[i].color = sc.nextInt(); 32 V[i].Vx = sc.nextDouble(); 33 V[i].Vy = sc.nextDouble(); 34 } 35 for (int i = 0; i < n; i++) { 36 for (int j = 0; j < n; j++) { 37 if (i != j && (V[i].color == 1) && (V[j].color == 0) && (V[i].Vx > V[j].Vx) && (V[i].Vy > V[j].Vy)) { 38 graph[i][j] = 1; 39 } 40 } 41 } 42 } 43 44 // 显示匹配结果 45 public void show() { 46 Arrays.fill(visit, 0); 47 for (int i = 0; i < n; i++) { 48 if (visit[i] == 0) { 49 if (matched[i] != -1) { 50 System.out.println("(" + V[i].Vx + "," + V[i].Vy + ")与" + "(" + V[matched[i]].Vx + "," 51 + V[matched[i]].Vy + ")" + "匹配"); 52 visit[i] = 1; 53 visit[matched[i]] = 1; 54 } 55 } 56 } 57 } 58 59 /* 60 * dfs实现, params: x:起始的未匹配点 return: 1:找到增广路 0:未找到 61 */ 62 public int dfs_solve(int x) { 63 // 找到一个和节点存在边的点,并且该点在本轮中没有被访问过 64 for (int i = 0; i < n; i++) { 65 if (graph[x][i] != 0 && visit[i] == 0) { 66 visit[i] = 1; // 标记为匹配过 67 // 按照交替路的模式找增广路,增广路相对于交替路的特性是就是,第一个节点和最后一个节点都是未匹配过的节点 68 if (matched[i] == -1 || dfs_solve(matched[i]) == 1) { // 直接跳到matched[i]能够保证匹配边和未匹配边交替 69 // 说明找到了一个未匹配节点,将所有匹配边变为未匹配边,将所有未匹配边变为匹配边,这样匹配边数会加1,这个交换过程通过回溯实现 70 71 matched[x] = i; 72 matched[i] = x; 73 74 System.out 75 .println("(" + V[x].Vx + "," + V[x].Vy + ") 与 " + "(" + V[i].Vx + "," + V[i].Vy + ")" + "匹配"); 76 return 1; 77 } 78 } 79 } 80 return 0; 81 } 82 83 public void hungarian1() { 84 Arrays.fill(matched, -1); 85 int sum = 0; 86 for (int i = 0; i < n; i++) { 87 if (matched[i] == -1) { 88 System.out.println("从 " + "(" + V[i].Vx + "," + V[i].Vy + ")" + " 开始匹配"); 89 Arrays.fill(visit, 0);// 重置浏览数组,用来浏览邻接矩阵当前列 90 sum += dfs_solve(i); 91 } 92 } 93 System.out.println("\n"+"最后共有 " + sum + " 匹配项"); 94 show(); 95 } 96 97 public static void main(String[] args) { 98 MaxMatching mm = new MaxMatching(); 99 mm.Init(); 100 mm.hungarian1(); 101 } 102 }
来源:博客园
作者:脑热
链接:https://www.cnblogs.com/Unicron/p/11574652.html