GCJ Practice Contest Problem C:
In this problem, u r asked to calculate the number of all the Hamiltonian Circles in complete graph only with at most 15 forbidden edges.
We know, finding the Hamiltonian Circles is a NP problem, how can we count all the Hamiltonian Circles in a graph with so many edges?
First, let us think about this problem. Give u a complete graph with N vertexes , can u tell me how many Hamiltonian Circles exist in it?
We can easily find that number will be (N-1)! / 2.
And back to the original problem, we find that the forbidden edges are very small. So we come up with an idea, we can use the number of Hamiltonian Circles in a complete graph minus those circles using forbidden edges.

Code
#include <iostream>
#include <vector>
using namespace std;
const int MOD = 9901;
const bool DB = false;
struct Edge
{
int s, t;
};
vector<int> edge[310];
Edge forb[16];
int N, K;
bool vis[310];
int fact[310];
int DFS(int now, int parent)
{
for (int i = 0; i < edge[now].size(); ++i)
if (!vis[ edge[now][i] ] && edge[now][i] != parent)
{
vis[ edge[now][i] ] = true;
return DFS(edge[now][i], now) + 1;
}
return 1;
}
int Solve()
{
memset(vis, false, sizeof(vis));
for (int i = 0; i < N; i++)
if (edge[i].size() > 2) return 0;
int comp = 0;
for (int i = 0; i < N; i++)
if (edge[i].size() == 1 && !vis[i])
{
vis[i] = true;
DFS(i, -1);
++comp;
}
int zeros = 0;
for (int i = 0; i < N; ++i)
if (edge[i].size() == 0)
++zeros;
for (int i = 0; i < N; ++i)
{
if (edge[i].size() == 2 && !vis[i])
{
int depth = 0;
// vis[i] = true;
depth = DFS(i, -1);
if (DB) printf("depth = %d\n", depth);
if (depth == N+1) return 1;
else
{
if (DB)
printf("exit when i = %d\n", i);
return 0;
}
}
}
if (DB)
printf("zeros = %d, comp = %d\n", zeros, comp);
int totn = zeros + comp;
if (comp) return fact[totn - 1] * (1LL << (comp-1)) % MOD;
else
return (fact[totn - 1] / 2) % MOD;
}
int main()
{
int t;
freopen("C-large-practice.in", "r", stdin);
freopen("C-large_parctice.out", "w", stdout);
fact[1] = 1;fact[0] = 1;
for (int i = 2; i <= 301; i++)
fact[i] = fact[i-1] * i % MOD;
scanf("%d", &t);
for (int ctr = 1; ctr <= t; ctr++)
{
scanf("%d%d", &N, &K);
for (int i = 0; i < K; i++)
{
scanf("%d%d", &forb[i].s, &forb[i].t);
forb[i].s--, forb[i].t--;
}
int ans = 0, ret;
for (int i = 0; i < (1<<K); i++)
{
if (DB)
printf("*****************\n");
for (int j = 0; j < N; j++)
edge[j].clear();
int mult = 1;
for (int j = 0; j < K; j++)
if (i&(1<<j))
edge[forb[j].s].push_back(forb[j].t), edge[forb[j].t].push_back(forb[j].s), mult *= -1;
ret = Solve();
if (DB)
printf("with mask %d, ret = %d, mult = %d\n", i, ret, mult);
ans = (ans + mult * ret) % MOD;
if (DB)
printf("ans = %d\n", ans);
}
printf("Case #%d: %d\n", ctr, ans < 0 ? ans + MOD : ans );
}
return 0;
}