Problem:
Problem F:
Controlled Tournament
National Association of Tennis is planning to hold a tennis competition among professional
players. The competition is going to be a knockout tournament, and you are assigned the task
to make the arrangement of players in the tournament.
You are given the detailed report about all participants of the competition. The report contains
the results of recent matches between all pairs of the participants. Examining the data, you’ve
noticed that it is only up to the opponent whether one player wins or not.
Since one of your special friends are attending the competition, you want him to get the best
prize. So you want to know the possibility where he wins the gold medal. However it is not so
easy to figure out because there are many participants. You have decided to write a program
which calculates the number of possible arrangements of tournament in which your friend wins
the gold medal.
In order to make your trick hidden from everyone, you need to avoid making a factitive tourna-
ment tree. So you have to minimize the height of your tournament tree.
Input
The input consists of multiple datasets. Each dataset has the format as described below.
N M
R
11
R
12
. . .
R
1
N
R
21
R
22
. . .
R
2
N
...
R
N
1
R
N
2
. . .
R
NN
N
(2 ≤
N
≤ 16) is the number of player, and
M
(1 ≤
M
≤
N
) is your friend’s ID (numbered
from 1).
R
ij
is the result of a match between the
i
-th player and the
j
-th player. When
i
-th
player always wins,
R
ij
= 1. Otherwise,
R
ij
= 0. It is guaranteed that the matrix is consistent:
for all
i
≠
j
,
R
ij
= 0 if and only if
R
ji
= 1. The diagonal elements
R
ii
are just given for
convenience and are always 0.
The end of input is indicated by a line containing two zeros. This line is not a part of any
datasets and should not be processed.
Output
For each dataset, your program should output in a line the number of possible tournaments in
which your friend wins the first prize.
Sample Input
2 1
0 1
0 0
2 1
0 0
1 0
3 3
0 1 1
0 0 1
0 0 0
3 3
0 1 0
0 0 0
1 1 0
3 1
0 1 0
0 0 0
1 1 0
3 3
0 1 0
0 0 1
1 0 0
6 4
0 0 0 0 0 1
1 0 1 0 1 0
1 0 0 1 1 0
1 1 0 0 1 0
1 0 0 0 0 0
0 1 1 1 1 0
7 2
0 1 0 0 0 1 0
0 0 1 0 1 1 1
1 0 0 1 1 0 0
1 1 0 0 0 1 0
1 0 0 1 0 0 1
0 0 1 0 1 0 0
1 0 1 1 0 1 0
8 6
0 0 0 0 1 0 0 0
1 0 1 1 0 0 0 0
1 0 0 0 1 0 0 0
1 0 1 0 0 1 0 1
0 1 0 1 0 0 1 0
1 1 1 0 1 0 0 1
1 1 1 1 0 1 0 0
1 1 1 0 1 0 1 0
0 0
Output for the Sample Input
1
0
0
3
0
1
11
139
78

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
using namespace std;
const int MAXN = 1 << 16;
int n, m;
int bit1[MAXN]; // 二进制数中有多少个 1
int dp[20][10][MAXN];
vector<int> G[20];
int dfs(int u, int h, int bits) {
    if(bit1[bits] == 1) return 1;
    if((1 << h) < bit1[bits]) return 0;
    if(dp[u][h][bits] != -1) return dp[u][h][bits];
    else dp[u][h][bits] = 0;
    int& res = dp[u][h][bits];
    for(int i = bits & (bits - 1); i; i = bits & (i - 1)) {
        if((i >> u) & 1) {
            int j = bits ^ i;
            for(int k = 0; k < G[u].size(); k++) {
                int v = G[u][k];
                if((j >> v) & 1) {
                    res += dfs(u, h - 1, i) * dfs(v, h - 1, j);
                }
            }
        }
    }
    return res;
}
int main() {
    for(int i = 0; i < MAXN; i++) {
        bit1[i] = bit1[i >> 1] + (i & 1);
    }
    while(cin >> n >> m && (n + m)) {
        memset(dp, -1, sizeof dp);
        for(int i = 0; i < n; i++) G[i].clear();
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                int x;
                cin >> x;
                if(x) G[i].push_back(j);
            }
        }
        int h = ceil(log(n) / log(2));
        cout << dfs(m - 1, h, (1 << n) - 1) << endl;
    }
    return 0;

}
accuracy: 1
time_ms: 3660
memory_kb: 54992
final_rank: 6

code_snippet: #include<bits/stdc++.h>
using namespace std;
const int MAXN = 1 << 16;
int n, m;
int bit1[MAXN]; // 二进制数中有多少个 1
int dp[20][10][MAXN];
vector<int> G[20];
int dfs(int u, int h, int bits) {
    if(bit1[bits] == 1) return 1;
    if((1 << h) < bit1[bits]) return 0;
    if(dp[u][h][bits] != -1) return dp[u][h][bits];
    else dp[u][h][bits] = 0;
    int& res = dp[u][h][bits];
    for(int i = bits & (bits - 1); i; i = bits & (i - 1)) { // 枚举 bits 里的 1 选或不选的情况
        if((i >> u) & 1) {
            int j = bits ^ i;
            for(int k = 0; k < G[u].size(); k++) {
                int v = G[u][k];
                if((j >> v) & 1) {
                    res += dfs(u, h - 1, i) * dfs(v, h - 1, j);
                }
            }
        }
    }
    return res;
}
int main() {
    for(int i = 0; i < MAXN; i++) {
        bit1[i] = bit1[i >> 1] + (i & 1);
    }
    while(cin >> n >> m && (n + m)) {
        memset(dp, -1, sizeof dp);
        for(int i = 0; i < n; i++) G[i].clear();
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                int x;
                cin >> x;
                if(x) G[i].push_back(j);
            }
        }
        int h = ceil(log(n) / log(2));
        cout << dfs(m - 1, h, (1 << n) - 1) << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 3670
memory_kb: 54724
final_rank: 5

code_snippet: #include<bits/stdc++.h>
using namespace std;
const int MAXN = 1 << 16;
int n, m;
int bit1[MAXN]; // 二?制数中有多少个 1
int dp[20][10][MAXN];
vector<int> G[20];
int dfs(int u, int h, int bits) {
    if(bit1[bits] == 1) return 1;
    if((1 << h) < bit1[bits]) return 0;
    if(dp[u][h][bits] != -1) return dp[u][h][bits];
    else dp[u][h][bits] = 0;
    int& res = dp[u][h][bits];
    for(int i = bits & (bits - 1); i; i = bits & (i - 1)) {
        if((i >> u) & 1) {
            int j = bits ^ i;
            for(int k = 0; k < G[u].size(); k++) {
                int v = G[u][k];
                if((j >> v) & 1) {
                    res += dfs(u, h - 1, i) * dfs(v, h - 1, j);
                }
            }
        }
    }
    return res;
}
int main() {
    for(int i = 0; i < MAXN; i++) {
        bit1[i] = bit1[i >> 1] + (i & 1);
    }
    while(cin >> n >> m && (n + m)) {
        memset(dp, -1, sizeof dp);
        for(int i = 0; i < n; i++) G[i].clear();
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                int x;
                cin >> x;
                if(x) G[i].push_back(j);
            }
        }
        int h = ceil(log(n) / log(2));
        cout << dfs(m - 1, h, (1 << n) - 1) << endl;
    }
    return 0;

}
accuracy: 1
time_ms: 4070
memory_kb: 54852
final_rank: 8

code_snippet: #include <algorithm>
#include <cassert>
#include <cstring>
#include <iostream>

using namespace std;

#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)
#define TRACE(x) cout << #x << " = " << x << endl
#define _ << " _ " <<

typedef long long llint;

const int MAX = 16;

int R[MAX][MAX];
int f[5][MAX][1<<MAX];
int bio[5][MAX][1<<MAX];
int cookie, n;

int solve(int h, int w, int s) {
  if (bio[h][w][s] == cookie) return f[h][w][s];
  bio[h][w][s] = cookie;

  int cnt = 0;
  REP(i, n) 
    if (s&(1<<i)) cnt++;
  if (cnt == 1) return f[h][w][s] = (s>>w) & 1;

  int nh = 0;
  while (cnt > 1) nh++, cnt = (cnt + 1) / 2;
  if (nh > h) return f[h][w][s] = 0;

  f[h][w][s] = 0;
  for (int s1 = s; s1 > 0; s1 = s & (s1 - 1))
    if ((s1 & s) == s1) {
      if (!(s1 & (1<<w))) continue;
      if (s1 == s) continue;

      int s2 = s ^ s1;

      REP(i, n)
        if (s2 & (1<<i))
          if (R[w][i]) f[h][w][s] += solve(h-1, w, s1) * solve(h-1, i, s2);
    }
  return f[h][w][s];
}

int main(void) {
  int m;
  while (scanf("%d %d", &n, &m) == 2) {
    if (n == 0 && m == 0) break;

    --m;
    REP(i, n) REP(j, n) scanf("%d", &R[i][j]);

    cookie++;
    int h = 0, tmp = n;
    while (tmp > 1) tmp = (tmp + 1) / 2, h++;
    printf("%d\n", solve(h, m, (1<<n) - 1));
  }
  
  return 0;
}
accuracy: 1
time_ms: 4110
memory_kb: 20112
final_rank: 2

code_snippet: #include <algorithm>
#include <bitset>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>

#define repi(i,a,b) for(int i = (a); i < (b); i++)
#define rep(i,a) repi(i,0,a)
#define repd(i,a,b) for(int i = (a) ; i >= (b); i--)
#define repit(i,a) for(__typeof((a).begin()) i = (a).begin(); i!= (a).end(); i++)
#define all(u) (u).begin(),(u).end()
#define rall(u) (u).rbegin(),(u).rend()
#define UNIQUE(u) (u).erase(unique(all(u)),(u).end)

#define pb push_back
#define mp makek_pair
#define INF 1e9
#define EPS 1e-9
#define PI acos(-1.0)

using namespace std;

typedef long long ll;
typedef vector<int> vi;

int N, M, R[16][16], mem[1<<16][16][8];

int f(int s, int i, int h)
{
    if (mem[s][i][h] >= 0) return mem[s][i][h];
    if (!(s >> i & 1)) return 0;
    int sz = __builtin_popcount(s);
    if (sz == 1) return 1;

    int ret = 0;
    int M = 1 << h - 1;
    int m = sz - M;
    int tmp = s ^ 1 << i;
    for (int t = tmp; t; --t, t &= tmp) {
	int k = __builtin_popcount(t);
	if (m <= k && k <= M)
	    for (int j = 0; j < N; ++j)
		if (R[i][j])
		    ret += f(s ^ t, i, h - 1) * f(t, j, h - 1);
    }
    return mem[s][i][h] = ret;
}

void solve()
{
    memset(mem, -1, sizeof(mem));

    --M;
    rep(i,N) rep(j,N) cin >> R[i][j];

    cout << f((1 << N) - 1, M, 32 - __builtin_clz(N - 1)) << endl;
}

int main()
{
    while (cin >> N >> M && N)
	solve();

    return 0;
}
accuracy: 1
time_ms: 3650
memory_kb: 33940
final_rank: 3

code_snippet: #include <cstdio>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <climits>
#include <cfloat>
using namespace std;

template <size_t T>
bool prevSubset(bitset<T>& bs, const bitset<T>& mask)
{
    bs = bs.to_ulong() - 1ull;
    bs &= mask;
    if(bs.none())
        return false;
    return true;
}

int n, m;
vector<vector<int> > r;

vector<vector<vector<int> > > memo;

int solve(int d, int win, bitset<16> rest)
{
    if(rest.count() == 1)
        return 1;
    if(d == -1)
        return 0;

    if(memo[d][win][rest.to_ulong()] != -1)
        return memo[d][win][rest.to_ulong()];

    int ret = 0;
    bitset<16> bs1 = rest;
    while(prevSubset(bs1, rest)){
        bitset<16> bs2 = rest ^ bs1;
        if(bs1.count() > (1<<d) || bs2.count() > (1<<d))
            continue;
        if(!bs1[win])
            continue;

        for(int i=0; i<n; ++i){
            if(bs2[i] && r[win][i] == 1)
                ret += solve(d-1, win, bs1) * solve(d-1, i, bs2);
        }
    }

    return memo[d][win][rest.to_ulong()] = ret;
}

int main()
{
    for(;;){
        cin >> n >> m;
        if(n == 0)
            return 0;

        r.assign(n, vector<int>(n));
        for(int i=0; i<n; ++i){
            for(int j=0; j<n; ++j){
                cin >> r[i][j];
            }
        }

        int d = 1;
        while((1 << d) < n)
            ++ d;

        memo.assign(d, vector<vector<int> >(n, vector<int>(1<<n, -1)));
        cout << solve(d-1, m-1, (1<<n)-1) << endl;
    }
}
accuracy: 1
time_ms: 5410
memory_kb: 24440
final_rank: 7

code_snippet: #include <iostream>
#include <cstring>

using namespace std;

static int mem[16][1<<16][5];
int vs[16][16];
int lg[16] = {1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4};

int search(int win, int lose, int cnt, int n){
	if(~mem[win][lose][cnt]) return mem[win][lose][cnt];
	if(!lose) return mem[win][lose][cnt] = 1;
	if(cnt == 0) return mem[win][lose][cnt] = 0;
	int res = 0, loseBit = 0;
	for(int t=lose;t;t&=(t-1)) loseBit++;
	if(lg[loseBit] > cnt) return mem[win][lose][cnt] = 0;
	for(int i=0;i<n;i++){
		if(!(lose&(1<<i))) continue;
		if(!vs[win][i]) continue;
		int mask = lose^(1<<i);
		int b = mask;
		do{
			res += search(win, b, cnt-1, n) * search(i, mask^b, cnt-1, n);
			b = (b-1)&mask;
		} while (b != mask);
	}
	return mem[win][lose][cnt] = res;
}

int main(){
	int n, m;
	while(cin >> n >> m, n){
		for(int i=0;i<n;i++)
			for(int j=0;j<n;j++)
				cin >> vs[i][j];
		memset(mem,-1,sizeof(mem));
		cout << search(m-1, (((1<<n)-1)^(1<<(m-1))), lg[n-1], n) << endl;
	}
}
accuracy: 1
time_ms: 3940
memory_kb: 20000
final_rank: 1

code_snippet: // Problem F : Controlled Tournament

#include <iostream>
#include <cstring>

using namespace std;

static int mem[16][1<<16][5];
int vs[16][16];
int lg[16] = {1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4};

// ツ講ツ評ツスツδ可イツドツつサツづ個づ慊づ慊づ個δδつ可サツ探ツ催オ
int search(int win, int lose, int cnt, int n){
	if(cnt < 0) return 0;
	if(~mem[win][lose][cnt]) return mem[win][lose][cnt];
	if(!lose) return mem[win][lose][cnt] = 1;
	int res = 0, loseBit = 0;
	for(int t=lose;t;t&=(t-1)) loseBit++;
	if(lg[loseBit] > cnt) return mem[win][lose][cnt] = 0;
	for(int i=0;i<n;i++){
		if(!(lose&(1<<i))) continue;
		if(!vs[win][i]) continue;
		int mask = lose^(1<<i);
		int b = mask;
		do{
			res += search(win, b, cnt-1, n) * search(i, mask^b, cnt-1, n);
			b = (b-1)&mask;
		} while (b != mask);
	}
	return mem[win][lose][cnt] = res;
}

int main(){
	int n, m;
	while(cin >> n >> m, n){
		for(int i=0;i<n;i++)
			for(int j=0;j<n;j++)
				cin >> vs[i][j];
		memset(mem,-1,sizeof(mem));
		cout << search(m-1, (((1<<n)-1)^(1<<(m-1))), lg[n-1], n) << endl;
	}
}
accuracy: 1
time_ms: 4460
memory_kb: 20000
final_rank: 4