给了一些点的关系,求拓扑序的个数,点很少可以跑暴力。最近学习状态压缩就写了一发。
最多16个点,可以把现在选出来的点的个数进行状态压缩。总共(1<<16)个状态。
枚举每个状态然后找出当前状态下入度为零的不在当前状态中的点。
状态转移方程:dp[i|j] += dp[i];
dp[0] = 1;
#include<cstdio>
#include<map>
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
string mp[20];
int tot;
int dp[(1<<16)+10];
struct node{
int to;
int next;
node(){
}
node(int a,int b):to(a),next(b){
}
}edge[400];
int head[20];
int in[20];
int d;
void add(int u,int v)
{
edge[d] = node(v,head[u]);
head[u] = d++;
}
int getid(string s)
{
for(int i=0;i<tot;i++)
if(mp[i]==s)
return i;
mp[tot] = s;
return tot++;
}
void check(int s)
{
memset(in,0,sizeof(in));
for(int i=0;i<tot;i++)
{
if(s&(1<<i)) continue;
for(int j=head[i];j!=-1;j=edge[j].next)
{
int to = edge[j].to;
in[to]++;
}
}
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
tot = 0;
d = 0;
string s1,s2;
memset(head,-1,sizeof(head));
memset(dp,0,sizeof(dp));
for(int i=0;i<n;i++)
{
cin>>s1>>s2;
int u = getid(s1);
int v = getid(s2);
add(u,v);
}
dp[0] = 1;
int bit = 1<<tot;
for(int i=0;i<bit;i++)
{
check(i);
for(int j=0;j<tot;j++)
{
if(in[j]==0)
{
int k = 1<<j;
if(i&k) continue;
int tmp = i|(1<<j);
dp[tmp] += dp[i];
}
}
}
printf("%d\n",dp[bit-1]);
}
return 0;
}