题意:给一个有向无环图,且0无入边,1无出边,有一个机器人,从1号点走到n点,每次有等概率原地不动或者向任意一条出边走,每次走的花费是已经过了的天数。求走到n时的期望花费。
思路:
先求期望时间,再求期望花费。
定义t[i]为i到n所需要的时间,定义dp[i]为i到n所需要的花费,j为i的出边的终点。
逆向拓扑。
这样做似乎是合理的....因为每次t和dp都是平均值然后相加,将ti倒过来相加似乎也没什么问题。(不会证明
/* Author : Rshs
* Data : 2019-09-03
*/
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const double pai = acos(-1);
const LL mod = 1e9+7;
const int MX = 1e5+5;
int chu[MX];
vector<int>g[MX],rg[MX];
double t[MX],dp[MX];
void Main(int avg){
int n,m;scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) rg[i].clear(),g[i].clear(),chu[i]=0;
for(int i=1;i<=m;i++){
int IA,IB;scanf("%d%d",&IA,&IB);
g[IA].push_back(IB);
rg[IB].push_back(IA);
chu[IA]++;
}
queue<int>q;q.push(n);t[n]=0,dp[n]=0;
while(!q.empty()){
int now=q.front();q.pop();
double szout=(double)g[now].size();
for(auto i:rg[now]){
chu[i]--;if(chu[i]==0)q.push(i);
}
if(now==n)continue;
t[now]=(szout+1)/szout;
for(auto i:g[now]){
t[now]+=t[i]/szout;
}
dp[now]=t[now]*(szout+1)/szout;
for(auto i:g[now]){
dp[now]+=dp[i]/szout;
}
}
printf("%.2lf\n",dp[1]);
}
int main(){
int cas;cin>>cas;for(int i=1;i<=cas;i++)Main(i);
return 0;
}