dp1[i] : 从i点到n点的期望天数
dp2[i]:从i点到n点的期望花费
out[i]:i点的出度
i,j之间有边,在i点时,机器人可到达j点,或者不动,概率相同。所以在i点有out[i]+1种选择,+1是代表不管机器人去哪,这一天都要加上。
同理:
因为是从后往前推,该题是有向无环图,所以建反边用拓扑排序。
code:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e5+5;
vector<int>e1[N],e2[N];
int t,n,m,u,v,cnt;
int out[N],in[N],a[N];
double dp1[N],dp2[N],res1,res2;
void init()
{
cnt=0;
for(int i=1;i<=n;i++)
e1[i].clear(),e2[i].clear(),out[i]=in[i]=0;
}
void topu()
{
queue<int>q;
q.push(n);
a[++cnt]=n;
while(q.size())
{
int u=q.front();
q.pop();
for(auto v:e2[u])
{
in[v]--;
if(!in[v])
q.push(v),a[++cnt]=v;
}
}
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
init();
for(int i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
out[u]++;in[u]++;
e1[u].push_back(v);
e2[v].push_back(u);
}
dp1[n]=dp2[n]=0;
topu();
for(int i=2;i<=n;i++)
{
int u=a[i];
res1=res2=0;
for(auto v:e1[u])
res1+=dp1[v],res2+=dp2[v];
dp1[u]=(res1+out[u]+1)/out[u];
dp2[u]=(res2+(out[u]+1)*dp1[u])/out[u];
}
printf("%.2f\n",dp2[1]);
}
return 0;
}