ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

绿豆蛙的归宿

2022-02-06 08:31:42  阅读:174  来源: 互联网

标签:归宿 int esum 绿豆蛙 wh read include getchar


link

emm,题目本身并不见得很难,主要是有一个点必须理清楚。期望DP的计算需要遵守全期望公式,大概是\(E=\sum\limits_i^m p_i\times c_i\),也就是说你在搞清楚一个东西对于期望的贡献的同时还应该要知道它产生贡献的概率。这也就回答了为什么本题中只能逆推而不能顺推的问题。毕竟一个点要走到终点必须也只能经过它的某条出边,所以经过某条出边的概率是一定的;而顺推时,你要从某条入边到当前点的概率为来点被经过的概率再除以来点的出度,显然要麻烦一些。但第二种也并不是不能写,可以考虑对期望贡献进行拆分,计算每条边被贡献的概率,递推时只用计算经过某个点的概率即可。于是就产生了两种写法:

第一种逆推:

#include<cstdio>
#include<queue>
#include<iostream>
//#define zczc
using namespace std;
const int N=200010;
inline void read(int &wh){
    wh=0;int f=1;char w=getchar();
    while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
    while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
    wh*=f;return;
}
int m,n,s1,s2,s3,d[N],s[N],a[N],cnt;
struct edge{int t,v,next;}e[N];
int head[N],esum;
inline void add(int fr,int to,int val){
	esum++;e[esum].t=to;
	e[esum].v=val;e[esum].next=head[fr];head[fr]=esum;
}
queue<int>q;
double f[N]={0};
signed main(){
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	read(m);read(n);
	for(int i=1;i<=n;i++){
		read(s1);read(s2);read(s3);
		add(s1,s2,s3);d[s2]++,s[s1]++;
	}
	for(int i=1;i<=m;i++)
		if(d[i]==0)q.push(i);
	while(!q.empty()){
		int now=q.front();q.pop();a[++cnt]=now;
		for(int i=head[now];i;i=e[i].next){
			if(--d[e[i].t]==0)q.push(e[i].t);
		}
	}
	f[m]=0;
	for(int i=m-1;i;i--){
		int wh=a[i];
		for(int j=head[wh];j;j=e[j].next){
			f[wh]+=(double)(f[e[j].t]+e[j].v)/s[wh];
		}
	}
	printf("%.2f",f[1]);
	return 0;
}

第二种贡献拆分:

#include<cstdio>
#include<queue>
#include<iostream>
//#define zczc
using namespace std;
const int N=200010;
inline void read(int &wh){
    wh=0;int f=1;char w=getchar();
    while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
    while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
    wh*=f;return;
}

int m,n,s1,s2,s3,d[N],s[N],a[N],cnt;
struct edge{
	int t,v,next;
}e[N];
int head[N],esum;
inline void add(int fr,int to,int val){
	esum++;
	e[esum].t=to;
	e[esum].v=val; 
	e[esum].next=head[fr];
	head[fr]=esum;
	return;
}

queue<int>q;
double f[N]={0},ans=0;

signed main(){
	
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	
	read(m);read(n);
	for(int i=1;i<=n;i++){
		read(s1);read(s2);read(s3);
		add(s1,s2,s3);d[s2]++;s[s1]++;
	}
	for(int i=1;i<=m;i++)if(d[i]==0)q.push(i);
	f[1]=1;
	while(!q.empty()){
		int now=q.front();q.pop();
		if(now==m)break;
		for(int i=head[now];i;i=e[i].next){
			f[e[i].t]+=f[now]/s[now];
			ans+=e[i].v*f[now]/s[now];
			if(--d[e[i].t]==0)q.push(e[i].t);
		}
	}
	printf("%.2f",ans);
	
	return 0;
}

这道黄题对于图上期望DP具有借鉴意义(吧)。

标签:归宿,int,esum,绿豆蛙,wh,read,include,getchar
来源: https://www.cnblogs.com/dai-se-can-tian/p/15865246.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有