题目
N N N 个人围坐一圈,有 M M M 对朋友关系。
第 i i i 对朋友关系是指,编号是 a i a_i ai 的人和编号是 b i b_i bi 的人是朋友。
现在要给他们安排座位,要求所有相邻的人不能是朋友。
问共有多少种方案?
如果两个方案只有旋转角度不同,则我们将其视为一种方案。
输入格式
第一行包含两个整数 N , M N,M N,M。
接下来 M M M 行,每行包含一对 a i , b i a_i,b_i ai,bi。
输出格式
输出一个数,表示总方案数。
数据范围
3
≤
N
≤
10
3 \le N \le 10
3≤N≤10,
0
≤
M
≤
N
(
N
−
1
)
2
0 \le M \le \frac{N(N-1)}{2}
0≤M≤2N(N−1),
1
≤
a
i
<
b
i
≤
N
1 \le a_i < b_i \le N
1≤ai<bi≤N,
(
a
i
,
b
i
)
≠
(
a
j
,
b
j
)
(a_i,b_i) \neq (a_j,b_j)
(ai,bi)=(aj,bj),
所有输入均为整数。
输入样例1:
4 1
1 2
输出样例1:
2
输入样例2:
10 5
1 2
3 4
5 6
7 8
9 10
输出样例2:
112512
分析:
1、
对于题目中的座位排序会像古老电话一样,可以轮盘旋转等价。
i.e.
1 2 3
2 3 1
3 1 2
这三种排列是等价
的,去判断这种等价是很困难的。但是,因为可以旋转,所以每一个数字都有机会座位开头,我们如果规定必须用1开始,那么就一定不会出现等价的情况了
!
2、
对于已经排好了前x - 1
个的座位序列,第x
个如果想要加入数字 t
需要判断:
(1) .是否 第x - 1个和第x个在朋友关系中;
(2)
如果 x == n ,那么还要判断是否第x个和第一个在关系中;
刚开始在dfs()函数里面传入了str作为记录状态,结果T了。
n,m = map(int,input().split())
g = [[0 for i in range(n+1)] for j in range(n+1)]
for i in range(m):
a , b = map(int,input().split())
g[a][b] = 1 ; g[b][a] = 1;
asset = set()
import sys
sys.setrecursionlimit(2000)
def dfs(x,s):
global n
if x == n:asset.add(s)
for i in range(1,n+1):
a = int(s[-1]) ; b = int(s[0]) ; c = i
if g[a][c] == 0 :
if g[b][c] == 0 or x != n-1:
f = True
for t in s:
if int(t) == c: f = False
if f: dfs(x + 1 , s + str(c))
dfs(1,"1")
print(len(asset))
后来改为了path[ ] 数组来进行记录就AC了
n,m = map(int,input().split())
g = [[0 for i in range(n+1)] for j in range(n+1)]
for i in range(m):
a , b = map(int,input().split())
g[a][b] = 1 ; g[b][a] = 1;
asset = set()
import sys
sys.setrecursionlimit(2000)
path = [0] * n ; cnt = 0
def dfs(x):
global n,cnt
if x == n:cnt += 1
for i in range(2,n+1):
a = path[x - 1] ; b = path[0] ; c = i
if g[a][c] == 0 :
if g[b][c] == 0 or x != n-1:
f = True
for t in path:
if t == c: f = False
if f:
path[x] = c
dfs(x + 1)
path[x] = 0
path[0] = 1
dfs(1)
print(cnt)