結果
| 問題 |
No.261 ぐるぐるぐるぐる!あみだくじ!
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2021-09-07 23:00:13 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 14 ms / 5,000 ms |
| コード長 | 3,999 bytes |
| コンパイル時間 | 2,709 ms |
| コンパイル使用メモリ | 216,252 KB |
| 最終ジャッジ日時 | 2025-01-24 08:43:39 |
|
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 37 |
ソースコード
#include<bits/stdc++.h>
using namespace std;
#define rep(i,n) for(ll i=0;i<n;i++)
#define repl(i,l,r) for(ll i=(l);i<(r);i++)
#define per(i,n) for(ll i=(n)-1;i>=0;i--)
#define perl(i,r,l) for(ll i=r-1;i>=l;i--)
#define fi first
#define se second
#define pb push_back
#define ins insert
#define pqueue(x) priority_queue<x,vector<x>,greater<x>>
#define all(x) (x).begin(),(x).end()
#define CST(x) cout<<fixed<<setprecision(x)
#define vtpl(x,y,z) vector<tuple<x,y,z>>
#define rev(x) reverse(x);
using ll=long long;
using vl=vector<ll>;
using vvl=vector<vector<ll>>;
using pl=pair<ll,ll>;
using vpl=vector<pl>;
using vvpl=vector<vpl>;
const ll MOD=1000000007;
const ll MOD9=998244353;
const int inf=1e9+10;
const ll INF=4e17;
const ll dy[9]={0,1,-1,0,1,1,-1,-1,0};
const ll dx[9]={1,0,0,-1,1,-1,1,-1,0};
template<class T> inline bool chmin(T& a, T b) {
if (a > b) {
a = b;
return true;
}
return false;
}
template<class T> inline bool chmax(T& a, T b) {
if (a < b) {
a = b;
return true;
}
return false;
}
struct UnionFind {
vector<int> par;
vector<int> edge;
UnionFind(int n) : par(n, -1),edge(n, 0) {}
int root(int x) {
if (par[x] < 0) return x;
else return par[x] = root(par[x]);
}
bool same(int x, int y) {
return root(x) == root(y);
}
bool merge(int x, int y) {
x = root(x); y = root(y);
if (x == y) {
edge[x]++;
return false;
}
if (par[x] > par[y]) swap(x, y);
par[x] += par[y];
par[y] = x;
edge[x] += edge[y]+1;
return true;
}
int size(int x) {
return -par[root(x)];
}
};
long long extGcd(long long a, long long b, long long &p, long long &q) {
if (b == 0) { p = 1; q = 0; return a; }
long long d = extGcd(b, a%b, q, p);
q -= a/b * p;
return d;
}
//-1が帰ってくる可能性に注意
pair<long long, long long> ChineseRem(const vector<long long> &b, const vector<long long> &m) {
long long r = 0, M = 1;
for (int i = 0; i < (int)b.size(); ++i) {
long long p, q;
long long d = extGcd(M, m[i], p, q); // p is inv of M/d (mod. m[i]/d)
if ((b[i] - r) % d != 0) return make_pair(0, -1);
long long tmp = (b[i] - r) / d * p % (m[i]/d);
r += M * tmp;
M *= m[i]/d;
}
return make_pair((r+M+M)%M, M);
}
int main(){
ll n,k;cin >> n >>k;
vl w(n);rep(i,n)w[i]=i;
rep(i,k){
ll a,b;cin >> a >> b;a--;b--;
swap(w[a],w[b]);
}
UnionFind uf(n);
rep(i,n)uf.merge(i,w[i]);
ll q;cin >> q;
while(q--){
vl v(n);rep(i,n)cin >> v[i],v[i]--;
bool ok=true;
rep(i,n){
if(!uf.same(i,v[i]))ok=false;
}
if(!ok){
cout << -1 << endl;
continue;
}
vl ans1,ans2;
set<ll> seen;
rep(i,n){
if(seen.count(uf.root(i)))continue;
seen.insert(uf.root(i));
map<ll,ll> now;
map<ll,ll> perm;
map<ll,ll> to;
rep(j,n){
if(uf.root(i)!=uf.root(j))continue;
perm[j]=w[j];
to[j]=v[j];
now[j]=j;
}
ll cnt=-1;
rep(_,to.size()){
if(now==to)cnt=_;
map<ll,ll> nmp;
for(auto p:now){
nmp[p.first]=perm[p.second];
}
swap(now,nmp);
}
ans1.push_back(cnt);
ans2.push_back(to.size());
}
ok=true;
for(auto p:ans1){
if(p==-1)ok=false;
}
if(!ok){
cout << -1 << endl;
continue;
}
auto answer=ChineseRem(ans1,ans2);
if(answer.second==-1)cout << -1 << endl;
else{
if(answer.first==0)answer.first+=answer.second;
cout << answer.first << endl;
}
}
}