【ybtoj】【期望问题】路径长度

题意

image

题解

乍一看:这也太简单了,纯纯的水题啊!
我原本的思路:\(dis_i\) 表示 \(1\)\(i\) 的期望距离,转移大致是 \(dis_v+=(dis_v+1.0*w_i)/oud_v\).
后来发现不对:对于每一条路选择的概率要传递下去,于是又加上一个数组 \(p_i\) 表示走到 \(i\) 的概率。
但是无法转移,简单的样例就足以说明一切。
这种做法的问题在于无法求出一条完整路径的期望距离。
看了题解拓宽思路:
更改 \(dis_i\) 的定义,改为从 \(i\) 出发到 \(n\) 的路径期望长度,那么 \(dis_i=(\sum dis_j+w(i,j))/oud_i\)
同时反向建图跑拓扑,就可以避免这个问题。
同时贴上正确代码和错误代码,方便比较区别。

错误代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int INF = 0x3f3f3f3f,N = 1e5+10,M = N<<1;
inline ll read()
{
	ll ret=0;char ch=' ',c=getchar();
	while(!(c>='0'&&c<='9')) ch=c,c=getchar();
	while(c>='0'&&c<='9') ret=(ret<<1)+(ret<<3)+c-'0',c=getchar();
	return ch=='-'?-ret:ret;
}
int n,m;
int ecnt=-1,head[N],oud[N],ind[N];
double dis[N],p[N];
struct edge
{
	int nxt,to,w; 
}a[M];
inline void add(int x,int y,int w)
{
	a[++ecnt]=(edge){head[x],y,w};
	head[x]=ecnt; 
}
queue<int> q;
void bfs()
{
	q.push(1);p[1]=1;
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		for(int i=head[u];~i;i=a[i].nxt)
		{
			int v=a[i].to;
			p[v]+=p[u]/oud[u];
			dis[v]+=dis[u]+1.0*a[i].w*p[v]; 
			ind[v]--;
			if(!ind[v]) q.push(v); 
		}
		printf("u=%d,dis[%d]=%.2lf\n",u,u,dis[u]);
	}
}
int main()
{
	n=read(),m=read();
	memset(head,-1,sizeof(head));
	for(int i=1;i<=m;i++) 
	{
		int u=read(),v=read(),w=read();
		add(u,v,w);
		oud[u]++,ind[v]++;
	}
	bfs();
	printf("%.2lf",dis[n]);
	return 0;
}

正确代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int INF = 0x3f3f3f3f,N = 1e5+10,M = N<<1;
inline ll read()
{
	ll ret=0;char ch=' ',c=getchar();
	while(!(c>='0'&&c<='9')) ch=c,c=getchar();
	while(c>='0'&&c<='9') ret=(ret<<1)+(ret<<3)+c-'0',c=getchar();
	return ch=='-'?-ret:ret;
}
int n,m;
int ecnt=-1,head[N],oud[N],ind[N];
double dis[N];
struct edge
{
	int nxt,to,w; 
}a[M];
inline void add(int x,int y,int w)
{
	a[++ecnt]=(edge){head[x],y,w};
	head[x]=ecnt; 
}
queue<int> q;
void bfs()
{
	q.push(n);
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		for(int i=head[u];~i;i=a[i].nxt)
		{
			int v=a[i].to;
			dis[v]+=(dis[u]+1.0*a[i].w)/oud[v]; 
			ind[v]--;
			if(!ind[v]) q.push(v); 
		}
		//printf("u=%d,dis[%d]=%.2lf\n",u,u,dis[u]);
	}
}
int main()
{
	n=read(),m=read();
	memset(head,-1,sizeof(head));
	for(int i=1;i<=m;i++) 
	{
		int u=read(),v=read(),w=read();
		add(v,u,w);
		oud[u]++,ind[u]++;
	}
	bfs();
	printf("%.2lf",dis[1]);
	return 0;
}
posted @ 2021-09-18 15:30  conprour  阅读(57)  评论(0编辑  收藏  举报