TopCoder SRM 589 Div1 Easy GooseTattarrattatDiv1

問題

英小文字からなる文字列が与えられる。
文字列に対して、文字x, yを選び、文字列に現れるすべてのxをyに置換することができる。
このときにかかるコストはxが現れている回数である。


この操作を繰り返し行い、文字列を回文になるようにしたい。
かかるコストの最小値はいくつか、求めよ。

制約条件

文字列の長さ≦50

方針

文字列をsとすると、
すべてのiについて、s[i]とs[n-i-1]が一致しなければならない。

aからzまでの26頂点からなるグラフを考える。
s[i]の文字とs[n-i-1]の文字の頂点に辺を張ったグラフを考える。


このグラフに対して、辺のある頂点はすべて一箇所にまとめなければならない。
頂点をまとめるのにかかるコストは頂点の重さ(文字の出現回数)に等しい。
なので、連結成分毎に、一番重い頂点にまとめればいい。

ソースコード

int cnt[26];
bool v[26], e[26][26];
pi rec(int c){
	v[c] = 1;
	pi res(cnt[c], cnt[c]);
	rep(i, 26) if(e[c][i] && !v[i]){
		pi p = rec(i);
		res.second += p.second;
		res.first = max(res.first, p.first);
	}
	return res;
}

class GooseTattarrattatDiv1 {
	public:
	int getmin(string S) {
		int ans = 0;
		memset(v, 0, sizeof(v));
		memset(e, 0, sizeof(e));
		memset(cnt, 0, sizeof(cnt));
		
		rep(i, S.size()){
			cnt[S[i] - 'a']++;
		}
		rep(i, S.size() / 2){
			int j = S.size() - 1 - i;
			e[S[i] - 'a'][S[j] - 'a'] = 1;
			e[S[j] - 'a'][S[i] - 'a'] = 1;
		}
		
		rep(i, 26) if(!v[i]){
			pi p = rec(i);
			ans += p.second - p.first;
		}
		return ans;
	}
};