解题思想:
对于图中所有节点,如果不相连,按照题意,必须在一个集合里;
所以其实可以从第一个节点入手,找出与该点不相邻点的所有节点组成一个集合;
判断剩余所有点,如果不和该集合中所有点都相连:按照题意,则无法构成完全多部图;
如果和该集合中所有点都相连,则;
我们可以考虑,如果一个完全多部图去掉其中一个集合,则剩余的集合也是一个完全多部图;
所以,本题可以采用递归的思想:如果剩下的点也是完全多部图,则整个集合就是完全多部图。
Base:
如果图中只有两个节点,则一定是完全多部图。(相连则划分为2个集合;不相连划分为一个集合)
代码实现(java)
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
public class MainJD01 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t = in.nextInt();
int n,m,x,y;
int[][] adjArr;
while(t-->0) {
n = in.nextInt();
m = in.nextInt();
adjArr = new int[n][n];
for (int i = 0; i < m; i++) {
x = in.nextInt();
y = in.nextInt();
adjArr[x-1][y-1] = 1;
adjArr[y-1][x-1] = 1;
}
List<Integer> list = new LinkedList<>();
for (int i = 0; i < n; i++) {
list.add(i);
}
if(judeg(list, adjArr))
System.out.println("Yes");
else
System.out.println("No");
}
in.close();
}
/*
* 1、
* 1.1 节点数小于等于2必为完全多部图
* 1.2 找出一个集合{节点互不相连}
* 2、判断剩下的点时候都和这个集合里的点相连
* 2.1 true:判断剩下节点是否是完全多部图
* 2.2 false:结束
*
*/
private static boolean judeg(List<Integer> list, int[][] adjArr) {
if(list.size() <= 2)
return true;
List<Integer> listMinis = new LinkedList<>();
listMinis.add(list.get(0));
list.remove(0);
for (int i = list.size()-1; i >= 0; i--) {
if(adjArr[list.get(i)][listMinis.get(0)] == 0) {//和第一个顶点无连接
listMinis.add(list.get(i));
list.remove(i);
}
}
for (int i = 0; i < listMinis.size(); i++) {
for (int j = 0; j < list.size(); j++) {
if(adjArr[list.get(j)][listMinis.get(i)] == 0)
return false;
}
}
return judeg(list, adjArr);
}
}
网上有个同学的想法是:
1、如果两点不相连,则必在同一个集合里;
2、同一个集合里的点因为需要与其他所有集合里的点都相连,所以关联的边数必须一致;
3、遍历邻接表中所有点,如果不相连,则必须其关联的边数必须一致,否则则视为不能构成多部图
该想法是单项的必要条件而非充要条件。
反例:(环形图)