题解 P7142 【[THUPC2021 初赛]密集子图】
考虑最短路树,对于深度为
这启发我们分层状压 dp。设
考虑转移。枚举深度为
直接实现即可做到
对于每个
需要进行一些卡常卡空间。
下面是我的最终代码,使用了滚动数组进行优化,空间
#include<bits/stdc++.h>
using namespace std;
inline int readint(){
int x=0;
bool f=0;
char c=getchar();
while(!isdigit(c)&&c!='-') c=getchar();
if(c=='-'){
f=1;
c=getchar();
}
while(isdigit(c)){
x=x*10+c-'0';
c=getchar();
}
return f?-x:x;
}
const int maxn=12;
int n,k;
const int mod=998244353;
int ksm(int a,int b){
int ans=1;
while(b){
if(b%2==1) ans=1ll*ans*a%mod;
a=1ll*a*a%mod;
b/=2;
}
return ans;
}
inline void mul(int& x,int y){
x=1ll*x*y%mod;
}
int p[maxn+5][maxn+5];
int f[2][(1<<maxn)+5][(1<<maxn)+5];
int g[(1<<maxn)+5][(1<<maxn)+5],h[(1<<maxn)+5][(1<<maxn)+5];
int main(){
#ifdef LOCAL
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
n=readint();
k=readint();
for(int i=0;i<n*(n-1);i++){
int x,y;
x=readint()-1;
y=readint()-1;
p[x][y]=readint();
mul(p[x][y],ksm(readint(),mod-2));
}
int all=(1<<n)-1;
for(int s1=0;s1<=all;s1++){
for(int i=0;i<n;i++) if(!(s1>>i&1)){
g[s1][1<<i]=1;
for(int j=0;j<n;j++) if(s1>>j&1) mul(g[s1][1<<i],(1-p[j][i]+mod)%mod);
}
for(int s2=all^s1;s2;s2=(s2-1)&(all^s1)) if((s2&-s2)!=s2){
g[s1][s2]=1;
for(int i=0;i<n;i++) if(s2>>i&1) mul(g[s1][s2],g[s1][1<<i]);
}
}
for(int s1=0;s1<=all;s1++){
for(int i=0;i<n;i++) if(!(s1>>i&1)) h[s1][1<<i]=(1-g[s1][1<<i]+mod)%mod;
for(int s2=all^s1;s2;s2=(s2-1)&(all^s1)) if((s2&-s2)!=s2){
h[s1][s2]=1;
for(int i=0;i<n;i++) if(s2>>i&1) mul(h[s1][s2],h[s1][1<<i]);
}
}
f[(k+1)%2][all][0]=1;
for(int d=k;d>=0;d--) for(int s1=1;s1<=all;s1++){
f[d%2][s1][0]=s1==all;
for(int s2=s1;s2;s2=(s2-1)&s1){
long long res=s1==all;
for(int s3=all^s1;s3;s3=(s3-1)&(all^s1))
res+=1ll*f[!(d%2)][s1|s3][s3]*g[s1^s2][s3]%mod*h[s2][s3]%mod;
f[d%2][s1][s2]=res%mod;
}
}
printf("%d\n",f[0][1][1]);
return 0;
}