結果
| 問題 |
No.3275 Minesweeper on Graph
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2024-07-31 14:04:25 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 249 ms / 2,000 ms |
| コード長 | 15,815 bytes |
| コンパイル時間 | 327 ms |
| コンパイル使用メモリ | 82,468 KB |
| 実行使用メモリ | 78,392 KB |
| 最終ジャッジ日時 | 2024-07-31 14:04:35 |
| 合計ジャッジ時間 | 9,623 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 40 |
ソースコード
import sys
import itertools
#import more_itertools
import time
import heapq
from math import radians, sin, cos, tan, sqrt, comb, pow
from math import log, log2, log10, exp
#from sortedcontainers import SortedSet, SortedDict, SortedList
from collections import deque
from operator import mul
from functools import reduce, cmp_to_key
from random import randint, randrange
from bisect import bisect_left, bisect_right
def input():
return sys.stdin.readline().replace('\n','')
#sys.setrecursionlimit(1000000)
md1 = 998244353
md2 = 10 ** 9 + 7
inf = 2 ** 31 + 1
primeset = set()
primelist = []
# 入力ツール
# 1行の入力を整数のリストとして受け取る
def intlist():
return list(map(int, input().split()))
# 1行から複数個の整数を受け取る
def getints():
return tuple(map(int, input().split()))
# n行の入力を文字列のリストとして受け取る
def strtable(n):
lst = []
for i in range(0, n):
lst.append(input())
return lst
# n行の入力を整数のリストとして受け取る
def inttable(n):
return list(map(int, strtable(n)))
# 整数のリストをn個受け取る
def intlisttable(n):
lst = []
for i in range(0, n):
lst.append(intlist())
return lst
# n個のクエリを先頭だけ整数、他を文字列のリストとして受け取る
def getquery(n):
lst = []
for i in range(0, n):
query = list(input().split())
qr = int(query[0])
lst.append((qr, query[1:]))
return lst
#==========
# 生成ツール
# H行W列のリスト生成
def twodimlist(h, w, init): # initの値で初期化
lst1 = []
for i in range(0, h):
lst2 = []
for j in range(0, w):
lst2.append(init)
lst1.append(lst2)
return lst1
# # 素数テーブルをsetとして生成
# def genprimeset(n): # n以下の素数を列挙
# global primeset
# pt = SortedSet(primeset)
# start = 2
# if len(pt) != 0:
# start = pt[-1]+1
# for i in range(start, n+1):
# pt.add(i)
# idx = 0
# while pt[idx] ** 2 <= pt[-1]:
# now = pt[idx] * 2
# while now <= pt[-1]:
# pt.discard(now)
# now += pt[idx]
# idx += 1
# return set(pt)
#==========
# 数え上げ
# 1次元数え上げ
def cntx(itr, x):
cnt = 0
for i in range(0, len(itr)):
if itr[i] == x:
cnt += 1
return cnt
# 2次元数え上げ
def twodimcntx(itr, x):
sm = 0
for i in range(0, len(itr)):
sm += cntx(itr[i], x)
return sm
# 全要素数え上げ
def allcnt(itr):
dct = {}
for i in range(0, len(itr)):
if itr[i] not in dct:
dct[itr[i]] = 0
dct[itr[i]] += 1
return dct
# 2次元全要素数え上げ
def twodimallcnt(itr, x):
dct = {}
for i in range(0, len(itr)):
for j in range(0, len(itr[i])):
if itr[i][j] not in dct:
dct[itr[i][j]] = 0
dct[itr[i][j]] += 1
return dct
#==========
# 計算ツール
# 最大公約数
def gcd(x, y):
if x < y:
return gcd(y, x)
if x % y == 0:
return y
return gcd(y, x%y)
# 最小公倍数
def lcm(x, y):
g = gcd(x, y)
return (x*y) // g
# フィボナッチ数列(0-indexで、a_0 = 0, a_1 = 1, 第n項まで生成)
def genfib(n, m): # m == 0ならmodなし、m == 1ならmd1でmod, m == 2ならmd2でmod
lst = [0, 1]
if m == 0:
for i in range(1, n):
lst.append(lst[-2]+lst[-1])
else:
md = md1
if m == 2:
md = md2
for i in range(1, n):
lst.append((lst[-2]+lst[-1])%md)
return lst
# 素数一覧の初期化
def primeinit(x):
global primeset, primelist
primeset = genprimeset(x)
primelist = list(primeset)
return
# 素数判定
def isitprime(x):
if x < 2:
return False
global primeset, primelist
if len(primeset) == 0:
primeinit(int(sqrt(x))+10)
elif primelist[-1] ** 2 < x:
primeinit(int(sqrt(x))+10)
if x in primeset:
return True
for i in range(0, len(primelist)):
if x % primelist[i] == 0:
return False
return True
# 素因数分解
def factorize(x):
global primeset, primelist
if len(primeset) == 0:
primeinit(int(sqrt(x))+10)
elif primelist[-1] ** 2 < x:
primeinit(int(sqrt(x))+10)
dct = {}
now = x
for i in range(0, len(primelist)):
if x < primelist[i] ** 2:
break
while now % primelist[i] == 0:
if primelist[i] not in dct:
dct[primelist[i]] = 0
dct[primelist[i]] += 1
now //= primelist[i]
if now != 1:
dct[now] = 1
return dct
# Coprime判定
def coprime(x, y):
return gcd(x, y) == 1
# 約数列挙
def divisor(x):
s = set()
for i in range(1, x+1):
if x < i ** 2:
break
if x % i == 0:
s.add(i)
s.add(x//i)
lst = sorted(list(s))
return lst
# 約数数え上げ
def countdivisor(x):
fact = factorize(x)
key = list(fact.keys())
cnt = 1
for i in range(0, len(key)):
cnt *= fact[key[i]] + 1
return cnt
# 大文字->小文字変換
def uppertolower(c):
if 'A' <= c and c <= 'Z':
return chr(ord(c)+32)
return c
# 小文字->大文字変換
def lowertoupper(c):
if 'a' <= c and c <= 'z':
return chr(ord(c)-32)
return c
# 大文字小文字相互変換
def upperlower(c):
newc = uppertolower(c)
if c == newc:
newc = lowertoupper(c)
return newc
# 文字列の大->小変換
def uppertolowerstr(s):
lst = []
for i in range(0, len(s)):
lst.append(uppertolower(s[i]))
return ''.join(lst)
# 文字列の大->小変換
def lowertoupperstr(s):
lst = []
for i in range(0, len(s)):
lst.append(lowertoupper(s[i]))
return ''.join(lst)
# 文字列の大小相互変換
def upperlowerstr(s):
lst = []
for i in range(0, len(s)):
lst.append(upperlower(s[i]))
return ''.join(lst)
# x以上の要素の個数
def xormore(lst, x): # lstはソート済みにすること
return len(lst) - bisect_left(lst, x)
# xより大きい要素の個数
def morethanx(lst, x): # lstはソート済みにすること
return len(lst) - bisect_right(lst, x)
# x以下の要素の個数
def xorless(lst, x): # lstはソート済みにすること
return bisect_right(lst, x)
# x未満の要素の個数
def lessthanx(lst, x): # lstはソート済みにすること
return bisect_left(lst, x)
# 各桁の総和
def digitsum(x):
nm = str(x)
sm = 0
for i in range(0, len(nm)):
sm += int(nm[i])
return sm
# bitカウント(64bitまで)
def popcount(x):
now = x
now = now - ((now >> 1) & 0x5555555555555555)
now = (now & 0x3333333333333333) + ((now >> 2) & 0x3333333333333333)
now = (now + (now >> 4)) & 0x0f0f0f0f0f0f0f0f
n = 8
for i in range(0, 3):
now += (now >> n)
n *= 2
return now & 0x0000007f
# xの累乗リスト(0乗からn乗まで)
def powtable(x, n, m): # modなしの場合はm = 0に設定する
md = m
if m == 1: # m == 1ならmd1でmod
md = md1
elif m == 2: # m == 2ならmd2でmod
md = md2
lst = [1]
for i in range(0, n):
if md == 0:
lst.append(lst[-1]*x)
else:
lst.append((lst[-1]*x)%md)
return lst
# 繰り返し2乗法
powdct = {}
def initpow():
global powdct
powdct = {}
powdct[0] = 1
return
def repeatpow(x, y, m):
global powdct
md = m
if m == 1:
md = md1
elif m == 2:
md = md2
if y in powdct:
return powdct[y]
a = 1
if y % 2 == 1:
a = x
if m == 0:
a = a*(repeatpow(x, y//2, m)**2)
else:
a = (a*(repeatpow(x, y//2, m)**2)) % md
powdct[y] = a
return a
def powit(x, y, m):
global powdct
initpow()
if x == 0:
return 0
return repeatpow(x, y, m)
# ==========
# リスト操作
# 値の交換
def swap(lst, x, y):
lst[x], lst[y] = lst[y], lst[x]
# 累積和(先頭を0にする)
def accum(itr):
lst = [0]
for i in range(0, len(itr)):
lst.append(lst[-1]+itr[i])
return lst
# itrをとりあえずリストに
def itrtolist(itr):
lst = []
for i in range(0, len(itr)):
lst.append(itr[i])
return lst
# 全ての順列
def permall(itr):
lst = itrtolist(itr)
return list(itertools.permutations(lst))
# itrの中身からn個を取り出す順列
def perm(itr, n):
if len(itr) < n:
return []
lst = itrtolist(itr)
return list(itertools.permutations(lst, n))
# itrの中身からn個を取り出す組合せ
def combi(itr, n):
if len(itr) < n:
return []
lst = itrtolist(itr)
return list(itertools.combinations(lst, n))
# 0-indexのリストを1-indexのdictに書き換え
def listtodict(lst):
dct = {}
for i in range(0, len(lst)):
dct[i+1] = lst[i]
return dct
# ==========
# グラフツール
# グラフの初期化
def defgraph(vlist):
graph = {}
for i in range(0, len(vlist)):
graph[vlist[i]] = set()
return graph
# 重み付きグラフの初期化
def defgraphw(vlist):
graph = {}
for i in range(0, len(vlist)):
graph[vlist[i]] = {}
return graph
# 無向グラフ生成
def undirgraph(vlist, elist): # 辺の形式は(u, v)
graph = defgraph(vlist)
for i in range(0, len(elist)):
u = elist[i][0]
v = elist[i][1]
graph[u].add(v)
graph[v].add(u)
return graph
# 重み付き無向グラフ生成
def undirgraphw(vlist, elist, wdict):
graph = defgraphw(vlist)
for i in range(0, len(elist)):
u = elist[i][0]
v = elist[i][1]
graph[u][v] = wdict[elist[i]]
graph[v][u] = wdict[elist[i]]
return graph
# 有向グラフ生成
def dirgraph(vlist, elist): # 辺の形式は(u, v)で、向きはu -> v
graph = defgraph(vlist)
for i in range(0, len(elist)):
u = elist[i][0]
v = elist[i][1]
graph[u].add(v)
return graph
# 重み付き有向グラフ生成
def dirgraphw(vlist, elist, wdict):
graph = defgraphw(vlist)
for i in range(0, len(elist)):
u = elist[i][0]
v = elist[i][1]
graph[u][v] = wdict[elist[i]]
return graph
# 重み無し最短ステップ
def shortest(vlist, elist, graph, st, gl):
if st not in graph or gl not in graph:
return -1
yet = set(vlist)
q = deque()
q.append((st, 0))
yet.discard(st)
while len(q) != 0:
now = q.popleft()
v = now[0]
s = now[1]
if v == gl:
return s
lst = list(graph[v])
for i in range(0, len(lst)):
nxtv = lst[i]
if nxtv in yet:
yet.discard(nxtv)
q.append((nxtv, s+1))
return -1
# ダイクストラ
def dijkstra(vlist, elist, graph, st):
cur = {}
for i in range(0, len(vlist)):
cur[vlist[i]] = inf
cur[st] = 0
dist = {}
h = []
heapq.heapify(h)
heapq.heappush(h, (0, st))
while len(h) != 0:
now = heapq.heappop(h)
d = now[0]
v = now[1]
if v in dist:
continue
dist[v] = d
lst = list(graph[v].keys())
for i in range(0, len(lst)):
nxt = lst[i]
if nxt not in dist:
nxtd = dist[v] + graph[v][nxt]
cur[nxt] = min(cur[nxt], nxtd)
if cur[nxt] == nxtd:
heapq.heappush(h, (nxtd, nxt))
return dist
# Union-Find生成
def genunionfind(vlist, elist): # 辺の形式は(u, v)
graph = defgraph(vlist)
root = {}
vcnt = {}
flag = False
for i in range(0, len(vlist)):
root[vlist[i]] = vlist[i]
vcnt[vlist[i]] = 1
for i in range(0, len(elist)):
u = elist[i][0]
v = elist[i][1]
ur = root[u]
vr = root[v]
if ur == vr:
flag = True
else:
H = ur
L = vr
if vcnt[ur] < vcnt[vr]:
H = vr
L = ur
graph[H].add(L)
vcnt[H] += vcnt[L]
q = deque()
q.append(L)
while len(q) != 0:
now = q.popleft()
root[now] = H
lst = list(graph[now])
for j in range(0, len(lst)):
q.append(lst[j])
return (graph, root, vcnt, flag) # (グラフ, 根, 頂点の数, ループ検出)の形式で返す
# ==========
# fenwick木
fenwick = []
# fenwickを初期化
def initfenwick(n, init):
global fenwick
fenwick = []
for i in range(0, n+1):
fenwick.append(init)
return
# idx番目までの和を求める
def fwsum(idx):
sm = 0
now = idx
while now > 0:
sm += fenwick[now]
now -= -now & now
return sm
# idx番目の値にxを足す
def fwadd(idx, x):
global fenwick
now = idx
while now < len(fenwick):
fenwick[now] += x
now += -now & now
return
# 転倒数
def inversion(A):
global fenwick
initfenwick(len(A), 0)
sm = 0
for i in range(0, len(A)):
sm += i - fwsum(A[i])
fwadd(A[i], 1)
return sm
# ==========
# ハッシュ
Mset = set()
Mlist = []
# Mの候補の素数を生成
def initM():
global Mset, Mlist
a = 10 ** 9
for i in range(-10000, 10001):
if isitprime(a+i):
Mset.add(a+i)
Mlist = list(Mset)
return
# Bの累乗を生成
def genB(b, m, n):
lst = [1]
for i in range(0, n):
lst.append((lst[-1]*b)%m)
return lst
# ハッシュテーブル生成
def genH(b, m, s):
lst = [0]
for i in range(0, len(s)):
a = ord(s[i]) - ord('a') + 1
lst.append((b*lst[-1]+a)%m)
return lst
# 部分文字列のハッシュ値を求める
def Hval(Hlist, Blist, M, L, R):
return (Hlist[R] - Blist[R-L+1]*Hlist[L-1]) % M
# ハッシュを複数生成
def multihash(s):
global Mset, Mlist
if len(Mlist) == 0:
initM()
bm = {}
for i in range(0, 5):
b = randint(9900, 11000)
m = Mlist[randrange(0, len(Mlist))]
while (b, m) in bm:
b = randint(9900, 11000)
m = Mlist[randrange(0, len(Mlist))]
Blist = genB(b, m, len(s))
Hlist = genH(b, m, s)
bm[(b, m)] = (Blist, Hlist)
return bm
# 指定したb, mでハッシュ生成
def multihashconst(s, bmkey):
h = {}
for i in range(0, 5):
b = bmkey[i][0]
m = bmkey[i][1]
Blist = genB(b, m, len(s))
Hlist = genH(b, m, s)
h[(b, m)] = (Blist, Hlist)
return h
# ==========
# 【問題要約】
#
# ==========
# コードはここから書く
N, M = getints()
vlist = list(range(1, N+1))
A = intlist()
elist = []
for i in range(0, M):
U, V = getints()
elist.append((U, V))
graph = undirgraph(vlist, elist)
ans = []
for i in range(0, 2**N):
mineexists = []
now = i
for j in range(0, N):
mineexists.append(now % 2)
now //= 2
minecount = []
for j in range(0, N):
minecount.append(0)
for j in range(0, N):
v = vlist[j]
lst = list(graph[v])
for k in range(0, len(lst)):
minecount[j] += mineexists[lst[k]-1]
subflag = True
for j in range(0, N):
if minecount[j] != A[j]:
subflag = False
if subflag:
ans.append(mineexists)
if len(ans) == 0:
print('No')
else:
print('Yes')
chosen = randrange(0, len(ans))
print(' '.join(map(str, ans[chosen])))