2021.1.4 省选训练 CF113D Museum
暴力卡常
//可以加火车头(亲测用处不大)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 23//开大会TLE(?)
#define M 550
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*f;
}
int n,m;
double a[N],b[N],out[N],f[2][N][N],ans[N];
double E=1e-15;
int head[N],nxt[M],v[M],cnt;
inline void add(int x,int y)
{
v[++cnt]=y;
nxt[cnt]=head[x];
head[x]=cnt;
}
inline void DP(int s1,int s2,int x,int y)
{
double tmp[2][2];//减少乘法运算
tmp[0][0]=b[s1]*b[s2]*f[x][s1][s2];//期望的运算方法(错)
tmp[0][1]=b[s1]*a[s2]*f[x][s1][s2];
tmp[1][0]=a[s1]*b[s2]*f[x][s1][s2];
tmp[1][1]=a[s1]*a[s2]*f[x][s1][s2];
for(int i=head[s1];i;i=nxt[i])
for(int j=head[s2];j;j=nxt[j])
f[y][v[i]][v[j]]+=tmp[0][0];
for(int i=head[s1];i;i=nxt[i]) f[y][v[i]][s2]+=tmp[0][1];
for(int j=head[s2];j;j=nxt[j]) f[y][s1][v[j]]+=tmp[1][0];
f[y][s1][s2]+=tmp[1][1];
}
int main()
{
int s1,s2;
n=read();m=read();s1=read();s2=read();
if(n==1){printf("1\n");return 0;}//注意特判(错)
if(s1==s2)
{
for(int i=1;i<=n;i++)
if(i==s1) printf("1 ");
else printf("0 ");
return 0;
}
int x,y;
for(int i=1;i<=m;i++)
{
x=read();y=read();
add(x,y),add(y,x);
out[x]+=1.0;
out[y]+=1.0;
}
for(int i=1;i<=n;i++) scanf("%lf",&a[i]),b[i]=(1.0-a[i])/out[i];
x=0;y=1;
f[x][s1][s2]=1.0;
int t=150000;
while(t--)//x->y 推表式
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(f[x][i][j]<=E) continue;//忽略过小的精度误差(卡精度)
if(i==j) continue;
DP(i,j,x,y);
}
for(int k=1;k<=n;k++) ans[k]+=f[y][k][k];
x^=1;y^=1;
memset(f[y],0,sizeof(f[y]));//注意清空(错)
}
for(int i=1;i<=n;i++) printf("%.12lf ",ans[i]);//需要手动调整输出精度
return 0;
}
高斯消元(待填)

浙公网安备 33010602011771号