zoj1346

来源:互联网 发布:钱箱测试软件 编辑:程序博客网 时间:2024/05/21 11:32

给了一些点的关系,求拓扑序的个数,点很少可以跑暴力。最近学习状态压缩就写了一发。

最多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;}


原创粉丝点击