P3232
P3232
显然将边被走过期望求出来,然后sort一下完事。
经典套路,边过多,考虑点上做文章。
显然的文章就是期望,那么\(f(i)\)表示经过点i的期望数,怎么球?
记\(X_t\)表示第t秒走到的点,那么
\[f(i)=E[\sum_{t=0}^{\infty}I_t(i)]=\sum_{t=0}^{\infty}P(x_t=i)
\]
用全概率公式就是
\[\begin{align}
f(i)&=\sum_{t=0}^{\infty} \sum_j \frac{1}{dep_{j}}P(X_{t-1}=j)P(X_t=i)\\
&=\sum_{j}\frac{1}{dep_j}P(X_{t-1}=j)\\
&=\sum_{j}\frac{1}{dep_j}f(j)\\
\end{align}
\]
那么显然用高斯消元即可解决。
\[\begin{cases}
f(i)=\sum_{(i,j) \in E,j!=N}f_j,1<i< n
f(i)=\sum_{(i,j) \in E,j!=N}f_j+1,i=1
\end{cases}
\]
code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ld long double
void rd(ll& x)
{
char ch=getchar();
ll f=1;x=0;
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-48;
ch=getchar();
}
x=x*f;
}
const ll N_ = 505,esp=1e-8;
ld ans,f[N_],a[N_][N_],b[N_];
ll N,M,d[N_];
vector<ll> q[N_];
struct Node{
ll u,v;ld val;
}edge[125010];
int main()
{
// freopen("P3232_4.in","r",stdin);
rd(N);rd(M);
for(int i=1;i<=M;i++){
ll u,v;
rd(u);rd(v);
edge[i]={u,v,0};
q[u].push_back(v);
q[v].push_back(u);
d[u]++;d[v]++;
}
for(int i=1;i<N;i++)
{
for(auto j:q[i]){
if(j==N)continue;
a[i][j]=1.0/d[j];
}
a[i][i]=-1;
if(i==1)b[i]=-1;
}
ll row=1;
// return 0;
for(int j=1;j<N;j++){
ll m=row;
for(int i=row;i<N;i++)
if(a[m][j]<a[i][j])m=i;
if(std::abs(a[m][j])<esp)continue;
for(int i=1;i<N;i++)swap(a[m][i],a[row][i]);
swap(b[m],b[row]);
for(int i=1;i<N;i++){
if(i==row)continue;
ld rate=a[i][j]*1.0/a[row][j];
for(int h=1;h<N;h++)a[i][h]-=rate*a[row][h];
b[i]-=rate*b[row];
}
row++;
}
// return 0;
for(int i=1;i<N;i++){
if(!a[i][i])cout<<0,exit(0);
f[i]=b[i]*1.0/a[i][i];
}
for(int i=1;i<=M;i++){
ll u=edge[i].u,v=edge[i].v;
edge[i].val=f[u]*1.0/d[u]+f[v]*1.0/d[v];
}
sort(edge+1,edge+1+M,[](Node x,Node y){
return x.val>y.val;
});
for(int i=1;i<=M;i++)ans=ans+(edge[i].val*i);
printf("%.3Lf",ans);
return 0;
}
小结:边过多,考虑点上做文章

浙公网安备 33010602011771号