TopCoder SRM 566 Div1 Easy PenguinSledding
問題
滑り台とは、座標平面上のn個の支点と、m本のパスであって、
パスは、異なる二つの支点をつないだ線分である。
滑り台のパスは交差していてはならない。
今、支点の数nと、支点と支点をつなぐパスm本が与えられる。
このパスのうち、いくつかを取り除いて、
支点が座標平面上のどの位置にあっても、パスが交差しないようにしたい。
パスの取り除き方は何通りあるか、求めよ。
制約条件
n≦50
m≦50
方針
滑り台の条件について考える。
長さ3以上の閉じていないパスがあったら、それは交差を作れるのでダメ。
また、互いに交わらない線分が2本あったら、それも交差を作れるのでダメ。
つまり、すべてのパスが連結で、長さが2以下であるか、
もしくは、パスがひとつの三角形なす場合のみが滑り台の条件を満たす。
長さが2以下の場合、一点からパスが伸びる形になるので、
始点をひとつ決めることで数え上げることができる。
ソースコード
class PenguinSledding { public: long long countDesigns(int n, vector <int> checkpoint1, vector <int> checkpoint2) { vector<vi> e(n); bool g[50][50] = {}; rep(i, checkpoint1.size()){ int a = checkpoint1[i], b = checkpoint2[i]; a--; b--; e[a].pb(b); e[b].pb(a); g[a][b] = g[b][a] = 1; } //パス0本の場合が1通り、パス1本のみの場合がm通り ll ans = 1 + checkpoint1.size(); rep(i, n) { ll t = e[i].size(); if(t <= 1) continue; //2^t通りのうち、1本だけ、0本の場合は最初に数えてある ans += 1ll << t; ans -= t + 1; } //三角形 rep(i, n) rep(j, i) rep(k, j){ if(g[i][j] && g[j][k] && g[k][i]) ans++; } return ans; } };