标签:back name namespace turn pre 需要 变长数组 iter 大量
概率这一个词语在生活中实际上是经常会碰见的,所以说这里我就来说一说相对而言遇到的要少一些的期望。这个期望啊,可以理解为某些事件大量发生以后的平均的结果。这就好比一个六面的色子扔了很多很多次以后,色子平均值会趋近于3.5
。这个原因啊,是显而易见,毫无疑问的,就不需要再多解释了。
好的,有一道例题可以看看
洛谷P4316
这一道题啊,读完了我就想到了拓扑排序,,同时用两个变长数组来存就可以了最开始我想用边集,可是我不知道怎么用边集来拓扑排序啊,于是ZhuFN大佬提醒我用两个变长数组。因此,我们只需要用两个变长数组,一个用来存点,一个用来存权值就OK了。
而这一个拓扑排序的过程中,相对与普通的拓扑排序,增加上对于期望长度的累加就可以了这是因为期望具有可加性
probab(u)
来的那一个点的期望长度,w
为这一条边的权值,outdgr(v)
为有几条路进来,那么可以得到
\[
probab(v)=[probab(u)+w]/outdgr(v)
\]
我们这里可采用正着来或反着来(应该是吧),就像是USACO的数字金字塔一样吧
#include<bits/stdc++.h>
#define maxn 100005
using namespace std;
queue<int> Q;
vector<int>G[maxn];
vector<int>W[maxn];
int n,tmp=0;
int indgr[maxn];
int outdgr[maxn];
double probab[maxn];
int m;
void topsort(){
Q.push(n);
while(!(Q.empty())){
int u=Q.front();
Q.pop();
vector<int>::iterator iterG=G[u].begin();
vector<int>::iterator iterW=W[u].begin();
while(iterG!=G[u].end()){
int v=*iterG,w=*iterW;
indgr[v]--;
probab[v]+=(probab[u]+w)/(outdgr[v]);
if(!indgr[v]){
Q.push(v);
}
iterW++;iterG++;
}
}
}
int main(){
memset(indgr,0,sizeof(indgr));
memset(outdgr,0,sizeof(outdgr));
memset(probab,0,sizeof(probab));
scanf("%d%d",&n,&m);
int a,b,c;
for(int i=1;i<=m;i++){
cin>>a>>b>>c;
indgr[a]++;outdgr[a]++;
G[b].push_back(a);
W[b].push_back(c);
}
topsort();
printf("%.2lf",probab[1]);
return 0;
}
这里再附上另外的大佬这道题的链接,我是看了dyx大佬代码以后才发现自己累加的地方做错了的对,没错,我最开始错了,而 ZhuFN则是用的dfs做的。
dyx
zfn
那么就可以了
标签:back name namespace turn pre 需要 变长数组 iter 大量
原文地址:https://www.cnblogs.com/perisino/p/10338652.html