链接
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1769
题解
黑心?出题人qwq(就不能写个spj吗
这题是高斯消元,每个点的期望次数等于它的所有前驱的(期望次数/前驱的出度)之和,
1
1
1号结点还要
+
1
+1
+1
由于是任意的图,所以很容易发现这个东西没法
d
p
dp
dp
考虑求解我列出的方程组,有些变量是解不出来的
比如下面这个情形:
1
→
2
1\rightarrow2
1→2
2
→
1
2\rightarrow1
2→1
3
→
1
3\rightarrow1
3→1
列出方程组:
{
e
1
=
1
+
e
2
+
e
3
e
2
=
0.5
e
1
e
3
=
0.5
e
1
\begin {cases} e_1=1+e_2+e_3\\ e_2=0.5e_1\\ e_3=0.5e_1 \end {cases}
⎩⎪⎨⎪⎧e1=1+e2+e3e2=0.5e1e3=0.5e1
消元得到了
0
=
1
0=1
0=1这样的等式
这样的情况下我确实得不到一个有界量来表示
e
1
,
e
2
,
e
3
e_1,e_2,e_3
e1,e2,e3
在实际情况中,这样的点应该是输出
i
n
f
inf
inf的
用高斯消元作处理之后,这样的变量表现出来的特点是系数为
0
0
0且常数项不等于
0
0
0
这题有个精度的问题:
不要把
e
i
e_i
ei的值提前算出来,因为算的时候你要除以系数,假如没除以系数之前常数项存的是
−
0.0000000000001
-0.0000000000001
−0.0000000000001,而实际上这里应该是
0
0
0,如果用
e
p
s
eps
eps判一下,你输出的是
0
0
0(正确√),但是假设系数很小,等于
0.00000000001
0.00000000001
0.00000000001,那么你做完除法之后再判
e
p
s
eps
eps,你就会认为这个数字不等于
0
0
0,从而你输出了
−
0.000
-0.000
−0.000(错误×)
出题人就不会写一个
s
p
j
spj
spj么qwq
代码
#include <bits/stdc++.h>
#define eps 1e-8
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define maxn 110
#define base 2000
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;
int read(int x=0)
{
int c, f=1;
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-48;
return f*x;
}
int cd[maxn], N, road[maxn][maxn], inf[maxn];
double mat[maxn][maxn], ans[maxn];
void gauss(double (*m)[maxn], int n)
{
int i, j, k, r;
for(i=1;i<=n;i++)
{
r=i;
for(j=i+1;j<=n;j++)if(fabs(m[j][i])>fabs(m[r][i]))r=j;
if(fabs(m[r][i])<eps)continue;
for(j=1;j<=n+1;j++)swap(m[i][j],m[r][j]);
for(j=1;j<=n;j++)
if(j!=i)
{
for(k=n+1;k>=i;k--)m[j][k]-=m[j][i]/m[i][i]*m[i][k];
}
}
}
void init()
{
int i, j, a, b;
cl(inf), cl(mat), cl(cd), cl(ans), cl(road);
while(a=read(), b=read(), a)
{
road[a][b]=1;
}
for(i=1;i<=N;i++)for(j=1;j<=N;j++)if(i!=j and road[i][j])cd[i]++;
for(i=1;i<=N;i++)mat[i][i]=1;
for(i=1;i<=N;i++)for(j=1;j<=N;j++)
{
if(i!=j and road[i][j])
{
mat[j][i]=-1.0/cd[i];
}
}
mat[1][N+1]=1;
}
void work()
{
int i, j;
gauss(mat,N);
for(i=N;i;i--)
{
if(fabs(mat[i][i])<eps and fabs(mat[i][N+1])>eps)
{
inf[i]=1;
}
for(j=i+1;j<=N;j++)if(fabs(mat[i][j])>eps and inf[j])inf[i]=1;
ans[i]=mat[i][N+1]/mat[i][i];
}
}
int main()
{
int q, x, kase=0;
while(N=read())
{
printf("Case #%d:\n",++kase);
init();
work();
q=read();
while(q--)
{
x=read();
if(inf[x])
{
printf("infinity\n");
}
else printf("%.3lf\n",fabs(mat[x][N+1])<eps ? 0.0 :mat[x][N+1]/mat[x][x]);
}
}
return 0;
}