资料:https://ozanerdem.github.io/jekyll/update/2019/11/17/representation-in-sat.html
from pysat.solvers import Glucose3
vertices_number=4 #顶点的数量
edges_number=3 #边的数量
str=input()
vertices_number,edges_number=str.split()
vertices_number=eval(vertices_number)
edges_number=eval(edges_number)
check_edges=[0]*(vertices_number*vertices_number+1)
#读入数据
for i in range(edges_number):
num=input()
num1,num2=num.split(' ')
num1=eval(num1)
num2=eval(num2)
check_edges[(num1-1)*vertices_number+num2]=1
check_edges[(num2-1)*vertices_number+num1]=1
g=Glucose3() #求解器的创建
#解决重复出现的问题
for i in range(0,vertices_number):
g.add_clause([-(i*vertices_number+i+1)])
for i in range(vertices_number):
for j in range(vertices_number):
for k in range(vertices_number):
if(j!=k):
g.add_clause([-(i*vertices_number+j+1),-(i*vertices_number+k+1)])
for i in range(0,vertices_number):
for j in range(0,vertices_number):
g.add_clause([-(i*vertices_number+1+j),-(j*vertices_number+1+i)])
#为每一步强制选择至少一个边缘
for i in range(vertices_number):
ls=list()
for j in range(vertices_number):
ls.append(i*vertices_number+1+j)
g.add_clause(ls)
#强制访问每个顶点
for i in range(vertices_number):
ls=list()
for j in range(vertices_number):
ls+=[j*vertices_number+1+i]
g.add_clause(ls)
#强制路径由真实边缘组成
for i in range(1,vertices_number*vertices_number+1):
if check_edges[i]!=1:
g.add_clause([-i])
g.solve()
if g.solve==False:
print('NO')
flag=0
while g.solve()==True:
ans=[0]
ans+=list(g.get_model())
now=0
the_ans=[1]
for i in range(1,vertices_number+1):
if(ans[i]==i):
now=i
the_ans+=[now]
while(True):
if(ans[(now-1)*vertices_number+1]==(now-1)*vertices_number+1):
break
for i in range(vertices_number):
if(ans[(now-1)*vertices_number+1+i]==(now-1)*vertices_number+1+i):
now=i+1
the_ans+=[now]
break
ls=list()
for i in range(1,vertices_number*vertices_number+1):
if ans[i]==i:
ls+=[-i]
g.add_clause(ls)
if len(the_ans)!=vertices_number:
continue;
else:
flag=1
for i in range(vertices_number):
print(the_ans[i],end=' ')
print(1)
if flag==0:
print('NO')