KUPC 2014 C - 占い

問題

A, BがいてAが数列a[i], Bが数列b[i]を持っている。
a[i]の長さはn, b[i]の長さはmである。


a[x[i]] = b[y[i]]という関係x[i], y[i]がc個与えられる。


二人が一緒に数を書いていく。
Aはk回目にa[k % n]を書いて、Bはk回目にb[k % m]を書く。
二人の数字が異なったら終了。
ただし、無限に終わらないa[i], b[i]のときは最初から数字を1個も書けないものとする。
二人は最大で何個の数字を書けるか。

方針

union-findで数字が同じである関係を、根が同じであるという関係として管理する。
根が違うノードが来たら、マージしてやる。
最後にマージしたのがi回目に書いた数字だとすると、iが答え。


LCM(n, m)回だけループをまわせばa[0], b[0]からに戻るので、
LCM(n, m)回だけ見れば十分だけど、制約が小さいのでn * m回まわして間に合う。

ソースコード

int n, m, q;
int p[500];
int root(int x){
	if(x == p[x]) return x;
	return p[x] = root(p[x]);
}
int main(){
	cin >> n >> m >> q;
	rep(i, n + m) p[i] = i;
	rep(i, q){
		int a, b; cin >> a >> b;
		a--; b--;
		a = root(a); b = root(b + n);
		if(a != b) p[b] = a;
	}
	int ans = 0;
	int a = 0, b = 0;
	
	rep(i, n * m){
		
		int x = root(a), y = root(b + n);
		if(x != y){
			ans = i + 1;
			p[y] = x;
		}
		a = (a + 1) % n; b = (b + 1) % m;
	}
	cout << ans << endl;
	
	return 0;
}