20201009校测
作者:互联网
国庆长假终于结束了
T1
太水了,跳过
T2
description:
给出一张n个点m条边的有向图,问其中有多少边的子集使得不存在任意一个环
data range:
\(N\le 17\)
solution:
code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=17,mod=1e9+7;
int n,m,pw[N*N];
int g[N+5][1<<N],num[1<<N],lg2[1<<N],dp[1<<N],tmp[1<<N];
inline int ct(int x)
{
int ans=0;
for(int i=0;(1<<i)<=x;++i)
if(x&(1<<i))++ans;
return ans;
}
inline int sig(int x){return (x&1)?-1:1;}
inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
int main()
{
scanf("%d%d",&n,&m);int M=1<<n;
for(int i=1;i<=m;++i)
{
int u,v;scanf("%d%d",&u,&v);
for(int j=0;j<M;++j)
if(j&(1<<(v-1)))++g[u][j];
}
pw[0]=1;for(int i=1;i<=m;++i)pw[i]=2ll*pw[i-1]%mod;
for(int i=0;i<M;++i)num[i]=ct(i);
for(int i=1;i<=n;++i)lg2[1<<(i-1)]=i;
dp[0]=1;
for(int zt=0;zt<M;++zt)
{
int bu=(M-1)^zt;
for(int j=bu;j;j=(j-1)&bu)
{
int s=bu^((j-1)&bu),lst=s&(-s);
tmp[s]=tmp[s^lst]+g[lg2[lst]][zt];
if(sig(num[s]+1)==1)dp[zt|s]=add(dp[zt|s],1ll*pw[tmp[s]]*dp[zt]%mod);
else dp[zt|s]=dec(dp[zt|s],1ll*pw[tmp[s]]*dp[zt]%mod);
}
}
cout<<dp[M-1];
return 0;
}
标签:有向图,17,int,题解,20201009,long,校测,mod 来源: https://www.cnblogs.com/zmyzmy/p/13788651.html