n, m = map(int, input().split()) edges = [list(map(int, input().split())) for _ in range(m)] boundary = [] for i, e in enumerate(edges): boundary.append([e[0], 0, i]) boundary.append([e[1], 1, i]) boundary.sort() num = [[0, 0, 0, 0]]#边界起点,边界起点到下一个边界点的覆盖次数,边界点的出现在起始点、终止点的次数;因为边界终止点不计入覆盖次数 i = 0 for b in boundary: if b[1] == 0: if b[0] == num[i][0]: num[i][1] += 1 num[i][2] += 1 else: num.append([b[0], num[i][1]+1, 1, 0]) i += 1 else: if b[0] == num[i][0]: num[i][1] -= 1 num[i][3] += 1 else: num.append([b[0], num[i][1]-1, 0, 1]) i += 1 # print(num) # 回溯方法搜索所有可能的选择方式 def dfs(ind, n_r):# 此处默认输入的n_r一定是合理的 if ind >= m: # print(n_r) return 1 #成功搜索完整个数组,没有中途中断,符合要求的一个解 # 不删除edge[ind] # for i in range(1, len(n_r)-1): # if n_r[i][1]<2: # return 0 # 当前情况无法满足覆盖要求,后续不需要再搜索 N = dfs(ind+1, [nu[:] for nu in n_r]) # 删除edge[ind] e = edges[ind] for i in range(1, len(n_r)): if n_r[i][0]==e[0]: n_r[i][2] -= 1 if n_r[i][0]==e[1]: n_r[i][3] -= 1 if n_r[i][0]>=e[0] and n_r[i][0]<e[1]:#删除某条边上对计数的贡献 n_r[i][1] -= 1 for i in range(1, len(n_r)-1):#这里漏掉最后一个点判断,循环后补上 if ((n_r[i][1]+n_r[i][3])<2) or (n_r[i][1]<2 and (n_r[i+1][0] - n_r[i][0])>2): # print(n_r) return N # 当前情况无法满足覆盖要求,后续不需要再搜索 if n_r[-1][3] < 2:#补上最后一个点判断 return N # print(n_r) N += dfs(ind+1, [nu[:] for nu in n_r]) return N # 判断当前的num是否满足要求 for i in range(1, len(num)-1):#这里漏掉最后一个点判断,循环后补上 if ((num[i][1]+num[i][3])<2) or (num[i][1]<2 and (num[i+1][0] - num[i][0])>2): print(0) exit(0) # 当前情况无法满足覆盖要求,后续不需要再搜索 if num[-1][3] < 2:#补上最后一个点判断 print(0) exit(0) N = dfs(0, [nu[:] for nu in num])#二维数组num需要使用深拷贝,所以作了循环生成 # print(num) print(N)