传送门

求期望的套路题

转化为每个点染成黑色期望的累加和

那么如果本来就是黑色,期望直接加上

如果是白色,概率是多少呢??实际上可以考虑这个点在多少的最短路径上

选点有种方式

再计算有条最短路径经过这个点,那么一次操作覆盖这个点概率为

那么至少覆盖一次期望就是

累加即可

至于一个点在多少最短路径上,弗洛伊德即可

然后这样判断

#include <bits/stdc++.h>
using namespace std;
#define int long long
int dis[509][509],n,m,k,color[509],vis[509];
const int mod = 1023694381;
int quick(int x,int n)
{
    int ans = 1;
    for( ; n ; n>>=1,x=x*x%mod )
        if( n&1 )    ans = ans*x%mod;
    return ans;
}
signed main()
{
    cin >> n >> m >> k;
    if( n>500 )
    {
        while(1  )    int s;
    }
    for(int i=1;i<=n;i++)    cin >> color[i];
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
        if( i!=j )    dis[i][j] = 1e16;
    for(int i=1;i<=m;i++)
    {
        int l,r,w; cin >> l >> r >> w;
        dis[l][r] = dis[r][l] = min( dis[l][r],w );
    }
    for(int k=1;k<=n;k++)
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
        dis[i][j] = min( dis[i][j],dis[i][k]+dis[k][j] );
    for(int i=1;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        for(int k=1;k<=n;k++)
            if( dis[i][j]==dis[i][k]+dis[k][j] ) vis[k]++;
    }
    int ans = 0, inv = quick(n*(n-1)/2,mod-2);
    for(int i=1;i<=n;i++)
    {
        if( color[i]==1 )    ans = ( ans+1 )%mod;
        else
        {
            int p = 1-quick(n*(n-1)/2-vis[i],k)*quick(inv,k)%mod;
            ans = ( ans+p )%mod;
        }
    }
    cout << (ans%mod+mod)%mod;
}