zoukankan      html  css  js  c++  java
  • 拓扑排序方案数的求法

    【描述】

    给定一个有向图,求拓扑排序生成的序列数

    【分析】

    我们知道当所有儿子节点排好序的时候,父节点就排好序了。

    这里我们定义一种状态:状态s的二进制位上的1表示此点已经排好序了。

    例如:s=6时,化为二进制s=110,表示第2、3个点已经排好序了。

    所以父节点的状态可以由子节点转移而来。

    用son[i]表示节点i可以进行转移的合法状态,f[s]表示状态为s的方法数。

    然后枚举所有的状态,然后在此状态中找二进制位上是0的点,如果这个点要求的合法状态是当前状态的子状态,那么可以由当前状态转移到把第i位设为1的状态。

    详见代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<ctime>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    #define FILE "read"
    #define up(i,j,n) for(ll i=j;i<=n;i++)
    namespace INIT{
    	char buf[1<<15],*fs,*ft;
    	inline char getc() {return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
    	inline ll read() {
    		ll x=0,f=1;  char ch=getc();
    		while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getc();}
    		while(isdigit(ch))  {x=x*10+ch-'0';  ch=getc();}
    		return x*f;
    	}
    }using namespace INIT;
    ll n,m,son[30],f[1<<17];
    int main(){
    	freopen(FILE".in","r",stdin);
    	freopen(FILE".out","w",stdout);
    	n=read();  m=read();
    	up(i,1,m)  {ll x=read(),y=read();  son[x]|=(1<<(y-1));}
    	f[0]=1;
    	up(s,0,(1<<n)-1) if(f[s]>0) up(i,1,n) if((s&son[i])==son[i]&&(s&(1<<(i-1)))==0)  f[s|(1<<(i-1))]+=f[s];
    	printf("%lld
    ",f[(1<<n)-1]);
    	return 0;
    }
    



  • 相关阅读:
    测试工程师入门要了解什么?(四)
    测试工程师入门要了解什么?(三)
    测试工程师入门要了解什么?(二)
    测试工程师入门要了解什么?(一)
    测试工程师专业术语
    测试场景标准库
    猜数字
    遍历
    python基础
    python class1
  • 原文地址:https://www.cnblogs.com/chty/p/6068110.html
Copyright © 2011-2022 走看看