P4316 绿豆蛙的归宿
前情提要,如果对期望的概念不清晰,请点击这里
我犯的错误:因为每条路只走一遍,而错误地判断每条路的概率相同
题解
1.对于任何一个节点来说,设其出边有\(len\)条,其子节点的期望长度为\(sum[j]\)
则该节点的期望长度为\(\frac{\sum sum[j]}{len}\),根据这个式子,做法就出来了(其实我也不会证明)
code 1
#include<bits/stdc++.h>
using namespace std;
vector<pair<int,int> > G[100005];
double sum[100005]={0};
double ss(int now)
{
if(sum[now])return sum[now];
int len=G[now].size();
for(int i=0;i<len;i++)
{
int next=G[now][i].first;
int val=G[now][i].second;
sum[now]+=(ss(next)+val)/len;
}
return sum[now];
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int u,v,w;
cin>>u>>v>>w;
G[u].push_back({v,w});
}
printf("%.2lf\n",ss(1));
return 0;
}
这个方法用来记忆化搜索和深度搜索,但是在数据较大时容易栈溢出,内存占用较大
code 2
#include<bits/stdc++.h>
using namespace std;
vector<pair<int,int> > G[100005];
double sum[100005]={0};
int out[100005]={0};
int out2[100005]={0};
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int u,v,w;
cin>>u>>v>>w;
G[v].push_back({u,w});
out[u]++;
out2[u]++;
}
queue<int> q;//广度优先搜索,一定程度上减少了递归造成的栈深度大和记忆化搜索访问造成的时间资源的浪费
q.push(n);
while(!q.empty())
{
int now=q.front();
q.pop();
for(int i=0;i<G[now].size();i++)
{
int head=G[now][i].first;
int val=G[now][i].second;
sum[head]+=(sum[now]+val)/out[head];
if(!--out2[head])q.push(head);//out2代表这个节点还有几个子节点没上线,等到全部上线后就能算这个节点了
}
}
printf("%.2lf\n",sum[1]);
return 0;
}

浙公网安备 33010602011771号