結果
問題 |
No.3275 Minesweeper on Graph
|
ユーザー |
|
提出日時 | 2024-07-31 14:06:11 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 33 ms / 2,000 ms |
コード長 | 15,277 bytes |
コンパイル時間 | 4,679 ms |
コンパイル使用メモリ | 308,472 KB |
実行使用メモリ | 6,948 KB |
最終ジャッジ日時 | 2024-07-31 14:06:20 |
合計ジャッジ時間 | 8,290 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 40 |
ソースコード
#include <bits/stdc++.h> #define ll long long #define ld long double #define um unordered_map #define us unordered_set using namespace std; const ll md1 = 998244353; const ll md2 = 1e9 + 7; const ll infll = LLONG_MAX; typedef tuple<ll, vector<string>> query; typedef vector<vector<ll>> twodint; //========== //入力ツール //n個の入力を1つの整数リストとして受け取る vector<ll> intlist(ll n){ vector<ll> v; for(ll i = 0; i < n; i++){ ll a; scanf("%lld", &a); v.push_back(a); } return v; } //n行の入力を文字列のリストとして受け取る vector<string> strtable(ll n){ vector<string> v; for(ll i = 0; i < n; i++){ string s; cin >> s; v.push_back(s); } return v; } //1行m個の整数の入力をn行受け取ってリストにする twodint intlisttable(ll n, ll m){ twodint v; for(ll i = 0; i < n; i++){ v.push_back(intlist(m)); } return v; } //n個のクエリを先頭だけ整数、他を文字列のリストとして受け取る vector<query> getquery(ll n){ //cin入力後に使う場合は、直前にgetline(cin)で改行を取り除く vector<query> v; v.clear(); string s; getline(cin, s); for(ll i = 0; i < n; i++){ stringstream ss(s); ll qr; vector<string> vs; ss >> qr; string inpt; while(ss >> inpt){ vs.push_back(inpt); } v.push_back({qr, vs}); getline(cin, s); } return v; } //========== //出力ツール //リストの中身を空白区切りで出力 template <typename T> void printwithspace(vector<T> v){ for(auto it = v.begin(); it != v.end(); it++){ if(it != v.begin()){ cout << " "; } cout << *it; } cout << endl; return; } //2次元リストの中身を1行ごと、空白区切りで出力 template <typename T> void twodprintwithspace(vector<vector<T>> v){ for(auto it = v.begin(); it != v.end(); it++){ for(auto it2 = (*it).begin(); it2 != (*it).end(); it2++){ if(it2 != (*it).begin()){ cout << " "; } cout << *it2; } cout << endl; } return; } //========== //unordered_map用の各種操作 //keyのリストを生成 template <typename T1, typename T2> vector<T1> keys(um<T1, T2> d){ vector<T1> v; for(auto it = d.begin(); it != d.end(); it++){ v.push_back((*it).first); } sort(v.begin(), v.end()); return v; } //valueのリストを作成 template <typename T1, typename T2> vector<T2> values(um<T1, T2> d){ vector<T2> v; for(auto it = d.begin(); it != d.end(); it++){ v.push_back((*it).second); } return v; } //========== //数え上げ //1次元数え上げ template <typename T1, typename T2> ll cntx(T1 itr, T2 x){ return count(itr.begin(), itr.end(), x); } //2次元数え上げ template <typename T1, typename T2> ll twodimcntx(T1 itr, T2 x){ ll sm = 0; for(auto it = itr.begin(); it != itr.end(); it++){ sm += cntx(itr, x); } return sm; } //1次元全要素数え上げ template <typename T1, typename T2> unordered_map<T2, ll> cntall(T1 itr){ unordered_map<T2, ll> d; for(auto it = itr.begin(); it != itr.end(); it++){ d.try_emplace(*it, 0); d[*it]++; } return d; } //2次元全要素数え上げ template <typename T1, typename T2> unordered_map<T2, ll> twodimcntall(T1 itr){ unordered_map<T2, ll> d; for(auto it = itr.begin(); it != itr.end(); it++){ for(auto it2 = (*it).begin(); it2 != (*it).end(); it2++){ d.try_emplace(*it2, 0); d[*it2]++; } } return d; } //========== //計算ツール //最大公約数 ll gcd(ll x, ll y){ if(x < y){ return gcd(y, x); } if(x % y == 0){ return y; } return gcd(y, x%y); } //最小公倍数 ll lcm(ll x, ll y){ ll g = gcd(x, y); return (x * y) / g; } //フィボナッチ数列生成(0-indexで、a_0 = 0, a_1 = 1, 第n項まで生成) vector<ll> genfib(ll n, ll m){ //m = 1ならmd1、m = 2ならmd2、それ以外ならmの値でmod ll md = m; if(m == 1){ md = md1; } else if(m == 2){ md = md2; } vector<ll> v = {0, 1}; for(ll i = 1; i < n; i++){ auto it1 = v.end() - 1; auto it2 = v.end() - 2; v.push_back(*it1 + *it2); } return v; } //各桁の総和 ll digitsum(ll x){ string s = to_string(x); ll sm = 0; for(auto it = s.begin(); it != s.end(); it++){ sm += *it - '0'; } return sm; } //popcount ll popcntll(ll x){ return static_cast<ll>(__builtin_popcountll(x)); } //xの累乗リスト(0乗からn乗まで) vector<ll> powtable(ll x, ll n, ll m){ //m = 1ならmd1, m = 2ならmd2, それ以外ならmでmod ll md = m; if(m == 1){ md = md1; } else if(m == 2){ md = md2; } vector<ll> v = {1}; for(ll i = 0; i < n; i++){ ll lst = *v.rbegin(); v.push_back((x*lst) % md); } return v; } //========== //素数関連 set<ll> primeset; vector<ll> primelist; //素数テーブル生成 void genprimeset(ll n){ ll start = 2; if(primelist.size() != 0){ start = *(primelist.rbegin()) + 1; } set<ll> ps = primeset; for(ll i = start; i <= n; i++){ ps.insert(i); } auto it = ps.begin(); ll m = *it; while(m*m <= (*ps.rbegin())){ ll now = m * 2; while(now <= (*ps.rbegin())){ if(ps.find(now) != ps.end()){ ps.erase(now); } now += m; } it++; m = *it; } primeset = ps; return; } //素数テーブルの初期化 void primeinit(ll x){ genprimeset(x); primelist.clear(); for(auto it = primeset.begin(); it != primeset.end(); it++){ primelist.push_back(*it); } return; } //素数判定 bool isitprime(ll x){ if(x < 2){ return false; } ll sr = static_cast<ll>(sqrt(x)); if(primelist.size() == 0){ primeinit(sr+10); } else{ ll p = *(primelist.rbegin()); if(p*p < x){ primeinit(sr+10); } } if(primeset.contains(x)){ return true; } for(auto it = primelist.begin(); it != primelist.end(); it++){ if(x % (*it) == 0){ return false; } } return true; } //素因数分解 tuple<vector<ll>, um<ll, ll>> factorize(ll x){ ll sr = static_cast<ll>(sqrt(x)); if(primelist.size() == 0){ primeinit(sr+10); } else{ ll p = *(primelist.rbegin()); if(p*p < x){ primeinit(sr+10); } } um<ll, ll> dct; ll now = x; for(auto it = primelist.begin(); it != primelist.end(); it++){ ll p = *it; if(x < p*p){ break; } while(now % p == 0){ if(!dct.contains(p)){ dct.insert({p, 0}); } dct[p] += 1; now /= p; } } if(now != 1){ dct.insert({now, 1}); } vector<ll> dctkey = keys(dct); return {dctkey, dct}; } //約数数え上げ ll countdivisor(ll x){ vector<ll> k; um<ll, ll> f; tuple<vector<ll>, um<ll, ll>> t = factorize(x); k = get<0>(t); f = get<1>(t); ll cnt = 1; for(auto it = k.begin(); it != k.end(); it++){ cnt *= f[*it] + 1; } return cnt; } //約数列挙 vector<ll> divisor(ll x){ us<ll> s; for(ll i = 1; i <= x; i++){ if(x < i*i){ break; } if(x % i == 0){ s.insert(i); s.insert(x / i); } } vector<ll> v; for(auto it = s.begin(); it != s.end(); it++){ v.push_back(*it); } sort(v.begin(), v.end()); return v; } //========== //英字変換 //大文字->小文字変換 char uppertolower(char c){ return static_cast<char>(toupper(c)); } //小文字→大文字変換 char lowertoupper(char c){ return static_cast<char>(tolower(c)); } //大文字小文字相互変換 char upperlower(char c){ char newc = uppertolower(c); if(c == newc){ newc = lowertoupper(c); } return newc; } //文字列の大文字->小文字変換 string uppertolowerstr(string s){ string a = ""; for(ll i = 0; i < s.size(); i++){ char& c = s[i]; a.push_back(uppertolower(c)); } return a; } //文字列の小文字->大文字変換 string lowertoupperstr(string s){ string a = ""; for(ll i = 0; i < s.size(); i++){ char& c = s[i]; a.push_back(lowertoupper(c)); } return a; } //文字列の大小相互変換 string upperlowerstr(string s){ string a = ""; for(ll i = 0; i < s.size(); i++){ char& c = s[i]; a.push_back(upperlower(c)); } return a; } //二分探索 //渡すvectorはソート済みにすること //x以下の要素の個数 template <typename T> ll xorless(vector<T> v, T x){ int ans = distance(v.begin(), upper_bound(v.begin(), v.end(), x)); return static_cast<ll>(ans); } //xより小さい要素の個数 template <typename T> ll lessthanx(vector<T> v, T x){ int ans = distance(v.begin(), lower_bound(v.begin(), v.end(), x)); return static_cast<ll>(ans); } //x以上の要素の個数 template <typename T> ll xormore(vector<T> v, T x){ int ans = v.size() - distance(v.begin(), lower_bound(v.begin(), v.end(), x)); return static_cast<ll>(ans); } //xより大きい要素の個数 template <typename T> ll morethanx(vector<T> v, T x){ int ans = v.size() - distance(v.begin(), upper_bound(v.begin(), v.end(), x)); return static_cast<ll>(ans); } //========== //繰り返し2乗法 um<ll, ll> powdct; //powdctの初期化 void initpow(){ powdct.clear(); powdct.insert({0, 1}); return; } ll repeatpow(ll x, ll y, ll m){//m = 1ならmd1, m = 2ならmd2, それ以外ならmでmod ll md = m; if(m == 1){ md = md1; } else if(m == 2){ md = md2; } if(powdct.contains(y)){ return powdct[y]; } ll a = 1; if(y % 2 == 1){ a = x; } ll r = repeatpow(x, y/2, m); a = (((r*r) % md)*a) % md; powdct.insert({y, a}); return a; } ll powit(ll x, ll y, ll m){ initpow(); if(x == 0){ return 0; } return repeatpow(x, y, m); } //========== //グラフツール(WIP) //グラフ初期化 template <typename T> vector<vector<ll>> defgraph(vector<T> vlist){ vector<vector<ll>> graph; for(ll i = 0; i < vlist.size(); i++){ vector<ll> vct; graph.push_back(vct); } return graph; } //elist生成(vlistはソート済みにすること) template <typename T> vector<tuple<ll, ll>> genelist(vector<T> vlist, vector<tuple<T, T>> rawe){ vector<tuple<ll, ll>> elist; for(ll i = 0; i < rawe.size(); i++){ T& u = get<0>(rawe[i]); T& v = get<1>(rawe[i]); auto uit = lower_bound(vlist.begin(), vlist.end(), u); auto vit = lower_bound(vlist.begin(), vlist.end(), v); ll uidx = static_cast<ll>(distance(vlist.begin(), uit)); ll vidx = static_cast<ll>(distance(vlist.begin(), vit)); elist.push_back({uidx, vidx}); } return elist; } //無向グラフ生成 template <typename T> vector<vector<ll>> undirgraph(vector<T> vlist, vector<tuple<T, T>> rawe){ vector<vector<ll>> graph = defgraph<T>(vlist); vector<tuple<ll, ll>> elist = genelist<T>(vlist, rawe); for(ll i = 0; i < elist.size(); i++){ ll& u = get<0>(elist[i]); ll& v = get<1>(elist[i]); graph[u].push_back(v); graph[v].push_back(u); } return graph; } //有向グラフ生成 template <typename T> vector<vector<ll>> dirgraph(vector<T> vlist, vector<tuple<T, T>> rawe){ vector<vector<ll>> graph = defgraph<T>(vlist); vector<tuple<ll, ll>> elist = genelist<T>(vlist, rawe); for(ll i = 0; i < elist.size(); i++){ ll& u = get<0>(elist[i]); ll& v = get<1>(elist[i]); graph[u].push_back(v); } return graph; } //重み無し最短経路 template <typename T> ll shortest(vector<T> vlist,\ vector<vector<ll>> graph,\ T st,\ T gl){ bool rule1 = find(vlist.begin(), vlist.end(), st) == vlist.end(); bool rule2 = find(vlist.begin(), vlist.end(), gl) == vlist.end(); if(rule1 || rule2){ return -1; } auto stitr = lower_bound(vlist.begin(), vlist.end(), st); auto glitr = lower_bound(vlist.begin(), vlist.end(), gl); ll stidx = static_cast<ll>(distance(vlist.begin(), stitr)); ll glidx = static_cast<ll>(distance(vlist.begin(), glitr)); us<ll> yet; for(ll i = 0; i < vlist.size(); i++){ yet.insert(i); } yet.erase(stidx); deque<tuple<ll, ll>> q; q.push_back({stidx, 0}); while(q.size() != 0){ tuple<ll, ll>& now = q.front(); ll& v = get<0>(now); ll& s = get<1>(now); q.pop_front(); if(v == glidx){ return s; } for(ll i = 0; i < graph[v].size(); i++){ ll nxtv = graph[v][i]; if(yet.contains(nxtv)){ yet.erase(nxtv); q.push_back({nxtv, s+1}); } } } return -1; } //wdictの生成 template <typename T1, typename T2> um<ll, T2> genwdict(vector<T1> vlist,\ vector<tuple<T1, T1, T2>> raww){ um<ll, T2> wdict; for(ll i = 0; i < raww.size(); i++){ T1& u = get<0>(raww[i]); T1& v = get<1>(raww[i]); T2& w = get<2>(raww[i]); auto uit = lower_bound(vlist.begin(), vlist.end(), u); auto vit = lower_bound(vlist.begin(), vlist.end(), v); ll uidx = static_cast<ll>(distance(vlist.begin(), uit)); ll vidx = static_cast<ll>(distance(vlist.begin(), vit)); ll widx = uidx * vlist.size() + vidx; wdict.insert({widx, w}); } return wdict; } //重み付きグラフ初期化 template <typename T1, typename T2> vector<um<ll, T2>> defgraphw(vector<T1> vlist){ vector<um<ll, T2>> graph; for(ll i = 0; i < vlist.size(); i++){ um<ll, T2> dct; graph.push_back(dct); } return graph; } //重み付き無向グラフ生成 template <typename T1, typename T2> vector<um<ll, T2>> undirgraphw(vector<T1> vlist,\ vector<tuple<T1, T1>> rawe,\ vector<tuple<T1, T1, T2>> raww){ vector<um<ll, T2>> graph = defgraphw<T1, T2>(vlist); vector<tuple<ll, ll>> elist = genelist<T1>(vlist, rawe); um<ll, T2> wdict = genwdict<T1, T2>(vlist, raww); for(ll i = 0; i < elist.size(); i++){ ll& u = get<0>(elist[i]); ll& v = get<1>(elist[i]); ll wref = u * vlist.size() + v; T2 w = wdict[wref]; graph[u].insert({v, w}); graph[v].insert({u, w}); } return graph; } /* //ダイクストラ(WIP) template <typename T1, typename T2> um<ll, T2> dijkstra(vector<T1> vlist,\ vector<tuple<ll, ll>> elist,\ vector<um<ll, T2>> graph,\ T1 st){ um<ll, T2> cur; for(ll i = 0; i < vlist.size(); i++){ cur.insert({i, static_cast<T2>(infll)}); } } */ //========== //問題要約 // N 頂点 M 辺の単純無向グラフが与えられる // 頂点には 1 から N までの番号が、辺には 1 から M までの番号が振られている // 辺 i(where 1<=i<=M)は頂点 U_i と頂点 V_i を結んでいる // 各頂点には地雷が 0 個または 1 個埋まっている // 頂点 k(where 1<=k<=N)に隣接する頂点に埋まっている地雷の個数の総和は A_k 個である // これに矛盾しない地雷の埋め方が存在するかを判定し、存在するなら埋め方を 1 つ例示せよ // // 1 <= N <= 16 // 1 <= M <= N(N-1) // 2 // 0 <= A_i <= N-1 // 1 <= U_i, V_i <= N // 入力はすべて整数 // グラフは単純無向グラフ // //========== //コードはここから書く int main(){ ll N, M; cin >> N >> M; vector<ll> vlist; for(ll i = 1; i <= N; i++){ vlist.push_back(i); } vector<ll> A = intlist(N); vector<tuple<ll, ll>> rawe; for(ll i = 0; i < M; i++){ ll U, V; cin >> U >> V; rawe.push_back({U, V}); } vector<vector<ll>> graph = undirgraph<ll>(vlist, rawe); ll mx = powit(2, N, 1); bool flag = true; for(ll i = 0; i < mx; i++){ vector<ll> mineexists; ll now = i; for(ll j = 0; j < N; j++){ mineexists.push_back(now % 2); now /= 2; } vector<ll> minecount; for(ll j = 0; j < N; j++){ minecount.push_back(0); } for(ll j = 0; j < N; j++){ for(ll k = 0; k < graph[j].size(); k++){ minecount[j] += mineexists[graph[j][k]]; } } bool subflag = true; for(ll j = 0; j < N; j++){ if(minecount[j] != A[j]){ subflag = false; } } if(subflag){ flag = false; cout << "Yes" << endl; printwithspace<ll>(mineexists); break; } } if(flag){ cout << "No" << endl; } return 0; }