密集子图(graph) - dp

题目大意:给一张有向完全图,每条边有一个出现概率p。问有多大的概率使得每个点离1号点的最短路不超过k。 n 12 n\le12
题解:考虑设dp[i,s,t]表示最短路不超过i的点集是s,最短路恰好是i的点集是t,转移枚举下一层,发现可以预处理转移的代价这部分是 O ( 4 n n ) O(4^nn) 的。然后这题略卡空间,需要处理 ( s , t ) > s (s,t)->s' 的映射来卡空间。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define reps(t,s) for(int t=(s);t;t=(t-1)&(s))//t!=0
#define inv(x) fast_pow(x,mod-2)
#define lint long long
#define mod 998244353
#define ull unsigned lint
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
const int N=14,MXS=531441+10,QWQ=(1<<12)+5;
int p[N][N],lb[MXS],val[MXS],val2[MXS],id[MXS],dp[N][MXS],tr[QWQ][QWQ];
inline int fast_pow(int x,int k,int ans=1) { for(;k;k>>=1,x=(lint)x*x%mod) if(k&1) ans=(lint)ans*x%mod;return ans; }
inline int upd(int &x,lint y) { return x=(x+y)%mod,0; }
namespace TRS_space{
    int n,qwq;inline int trs(int s,int t) { if(qwq) return tr[s][t];int res=0;for(int i=n-1;i>=0;i--) res=res*3+((s>>i)&1)+((t>>i)&1);return res; }
}using TRS_space::trs;
int main()
{
    int n=inn(),k=inn(),all=(1<<n)-1,a,b,v,x,y,v2,v3;TRS_space::n=n;
    rep(i,1,n*(n-1)) x=inn()-1,y=inn()-1,a=inn(),b=inn(),p[x][y]=(lint)a*fast_pow(b,mod-2)%mod;
    dp[0][trs(1,1)]=1;rep(i,1,all) lb[i]=(i&-i),val2[trs(i,i)]=1;rep(i,0,n-1) id[1<<i]=i;
    rep(i,1,all) reps(j,i) tr[i][j]=trs(i,j);TRS_space::qwq=1;
    rep(i,1,all) reps(j,i) if(i^j)
    {
        int s=i^j,t=j,&res=val[trs(i,j)],&res2=val2[trs(i,j)];res=res2=1;
        rep(a,0,n-1) if((t>>a)&1)
        {
            int qwq=1;rep(b,0,n-1) if((s>>b)&1) qwq=qwq*(1ll-p[b][a]+mod)%mod;
            res=res*(1ll-qwq+mod)%mod,res2=(lint)res2*qwq%mod;
        }
    }
    rep(i,0,k-1)
    {
        int *now=dp[i],*nxt=dp[i+1];
        rep(s,0,all) reps(t,s) if((v=now[trs(s,t)])) reps(r,s^all)
            if((v2=val[trs(t|r,r)])&&(v3=val2[trs(s^t^r,r)])) upd(nxt[trs(s|r,r)],(lint)v*v2%mod*v3);
    }
    int ans=0;rep(i,0,k) rep(s,1,all) if(dp[i][trs(all,s)]) upd(ans,dp[i][trs(all,s)]);return !printf("%d\n",ans);
}


猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/89336055
DP
DP?