2014
03-06

# Arborescence Counting

"In graph theory, an arborescence is a directed graph in which, for a vertex v called the root and any other vertex u, there is exactly one directed path rom v to u. In other words, an arborescence is a directed, rooted tree in which all edges point away from the root. Every arborescence is a directed acyclic graph."– from Wikipedia, the free encyclopedia

You are given a directed graph with N vertices, and your task is to count the number of different arborescences of size N that can be found in the given graph.

Two arborescences are considered different when they consist of different edges.

Input consists of multiple test cases.
For each test case, the first line contains one integer N described as above.
N lines follows, each consists of N characters, either ’0′ or ’1′, representing the adjacency matrix of the graph.
The directed graph contains edge (i,j) if and only if the jth character of the ith line of the matrix is ’1′.
The graph consists of no more than 8 vertices.
End of input is indicated by a line consisting of a single 0.

Input consists of multiple test cases.
For each test case, the first line contains one integer N described as above.
N lines follows, each consists of N characters, either ’0′ or ’1′, representing the adjacency matrix of the graph.
The directed graph contains edge (i,j) if and only if the jth character of the ith line of the matrix is ’1′.
The graph consists of no more than 8 vertices.
End of input is indicated by a line consisting of a single 0.

2
00
00
2
01
10
0

0
2

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAX_N = 8, MAX_S = 1 << MAX_N;
int n, m, t, dp[MAX_S][MAX_S];
char g[MAX_N][MAX_N + 1];

int main() {
while (scanf("%d", &n) != EOF) {
if (!n) break;
for (int i = 0; i < n; i ++) {
scanf("%s", g[i]);
for (int j = 0; j < n; j ++) g[i][j] -= '0';
}

int upper = 1 << n, ans = 0;
for (int i = 0; i < n; i ++) {
memset(dp, 0, sizeof(dp));
dp[1 << i][1 << i] = 1;

for (int s = mask; s; s = (s - 1) & mask)
for (int u = 0; u < n; u ++) if (mask & (1 << u))
for (int v = 0; v < n; v ++) if ((mask & (1 << v)) == 0 && g[u][v]) {
int m1 = mask | (1 << v);
int m2 = (s | (1 << v)) & (~(1 << u));
if (((1 << (v + 1)) - 1) >= m2) dp[m1][m2] += dp[mask][s];
}

for (int s = 0; s < upper; s ++) ans += dp[upper - 1][s];
}

printf("%d\n", ans);
}
return 0;
}