旅行的意义 (期望dp、图的dfs遍历-标记、逆元预处理)

知识点:有向无环图VS树 、期望dp

L. 旅行的意义

time limit per test

1.0 s

memory limit per test

256 MB

input

standard input

output

standard output

为什么有人永远渴望旅行,或许就因为,巧合和温暖会在下一秒蜂拥而至吧。

一直想去旅游的天天决定在即将到来的五一假期中安排一场环游世界的旅行。为此,他已经提前查阅了很多资料,并准备画一张旅游路线图。天天先将所有可能会去的 nn 个旅游城市依次编号标记为 1,2,⋯,n1,2,⋯,n。如果从城市 AA 到城市 BB 有一条直达的铁路线路,他就会在图上画上一条从 AA 向 BB 的有向线段。因为天天不喜欢把时间浪费在往返的乘车上,因此他设计的旅游地图路线是一个有向无环图。

天天身在 11 号城市,他每到达一个旅游城市都会先花一天的时间游玩当地的旅游景点。接下来他也没有明确的目的地,所以第二天他会随机地选择该城市的一条直达线路,花费一天的时间通往下一个旅游城市。当然,如果这个城市的旅游景点太好玩的话,他可能会选择再逗留一天,但是由于假期有限,他在当前的旅游城市最多只能呆 22 天。例如,当天天在城市 CC 时,若城市 CC 有 22 条直达线路分别通往城市 AA 和城市 BB,则在第一天的游玩过后,第二天他有 1313 的可能会选择继续逗留在城市 CC 多游玩一天,但是第三天他一定不会再逗留在城市 CC 了;同时他有 1313 可能会选择立即搭乘直达城市 AA 的高铁;他也有 1313 的可能会选择立即搭乘直达城市 BB 的高铁。

当天天把所有的旅游城市都游玩过后,他也就只能结束这段难忘的五一旅行假期了。现在请聪明的你帮天天提前计算一下,他本次旅行时间的期望是多少呢?

容易证明天天旅行时间的期望为 PQPQ 的形式,其中 PP 和 QQ 互质,且 Q≢0 (mod 998244353)Q≢0 (mod 998244353)。因此答案请以 P⋅Q−1 (mod 998244353)P⋅Q−1 (mod 998244353) 的形式输出,其中 Q−1Q−1 表示 QQ 在取模 998244353998244353 下的逆元。

Input

第一行输入一个正整数 T (1≤T≤10)T (1≤T≤10),表示数据组数。接下来 TT 组数据,每组数据均满足:

  • 第一行输入两个非负整数 n (1≤n≤105)n (1≤n≤105) 和 m (0≤m≤105)m (0≤m≤105),分别表示天天可能旅行的城市数量 nn 和它们之间的直达线路数量 mm。
  • 接下来 mm 行,每行输入两个正整数 uu 和 v (1≤u,v≤n)v (1≤u,v≤n),表示从城市 uu 到 vv 有一条单向直达线路,保证两个旅游城市之间最多只有 11 条直达线路。

Output

对于每组数据,请输出一个非负整数,表示天天旅行时间的期望,注意换行。

Example

input

Copy

2
1 0
2 1
1 2

output

Copy

2
499122181

Note

第一组样例只有一个旅游城市。首先,天天会在该城市游玩一天,第二天只剩下一个选择——留下来接着玩一天,再之后他就只能结束旅程了,所以旅游时间的期望是 22。

第二组样例由两个旅游城市,从城市 11 到城市 22 有一条直达的线路。天天首先在城市 11 游玩一天,然后有 1212 的概率前往城市 22,这将花费 11 天时间乘坐高铁;当然天天也有 1212 的概率逗留在城市 11 多玩一天,第三天再乘坐高铁前往城市 22。因此刚到达城市 22 时,天天花费的旅行时间期望是 1+[12⋅1+12⋅(1+1)]=2.51+[12⋅1+12⋅(1+1)]=2.5 天。接着天天会在城市 22 先游玩一天,但是接下来他没有其他城市可以去了,只能选择继续逗留一天然后终止旅程,容易算出本次旅程总的时间期望为 4.54.5 天,即 92=9⋅2−1 (mod 998244353)=49912218192=9⋅2−1 (mod 998244353)=499122181。

题目

解法:假设点u是末尾点,已经没有边连接其他点那么我从点u开始玩的期望的天数是2两天,玩了第一天没得选只能待在原地继续玩一天,我们倒推,设d[u]为从u为起点的开始玩的期望天数,假设u有sz条边连接其他点v,首先我必须在u点玩一天,d[u] = 1,接下来我有1 / (sz +1)的概率去每个连接的点v,那么d[u] += 1/(sz + 1) * (d[v] + 1),同时,我还有1/(sz + 1)的概率继续在点u玩,那么d[u] += 1 /(sz + 1),如果在u点玩了两天,那么接下来必须要去连接的v点,那么d[u] += 1 / (sz + 1) * 1 / sz * (d[v] + 1)

 

化简为:

d[u]=  1  +  1/(sz+1)  +   (1/sz+1  *  1/sz  +  1/sz+1  ) * d[v]    +1;

     初始期望 +  继续留期望    +  进入下个城市的概率*下个城市期望   +  高铁期望

 

--------------------- 
作者:一只叫橘子的猫 
来源:CSDN 
原文:https://blog.csdn.net/ccsu_cat/article/details/95448785 
版权声明:本文为博主原创文章,转载请附上博文链接!

重点:在求其他城市期望时,前应乘上来到这个城市的概率(p)*(d[v]+1) 此处加1 为高铁所需要浪费的天数

#include<bits/stdc++.h> 
using namespace std;
int n,m;
const int N=100005;
#define mod 998244353
vector<int > vect[N];//储存有向关系 
int vis[N]; //标记是否遍历过   
long long int dp[N],ny[N];//逆元数组-预处理
long long int ksm(long long int i)//!!!ksm return  ->long long  
{
	long long res=1;
	int y=mod-2;
	long long x=i;
	while(y)
	{
		if(y&1) res=res*x%mod;
		x=x*x%mod;
		y/=2;
	}
	return res;
}
void dfs(int u)
{
	if(vis[u]) return ;//图的dfs遍历    有向无环图  vs  树!!!! 

	dp[u]=1;//期望值初始化为1 
	vis[u]=1;
	int sz=vect[u].size();
	if(sz)  dp[u]+=1;
	for(auto v:vect[u])
	{
		dfs(v);
		//加上后面城市的期望值=d[v]*p 
		dp[u]=(dp[u]  +   ((ny[sz+1]+ny[sz+1]*ny[sz]%mod)%mod)  *  (dp[v]) %mod)%mod;
	}
	dp[u]=(dp[u]+ny[sz+1])%mod;//加上第二天继续留下来的期望 
}
int main()
{
	ny[1]=1;///!!!!!1的逆元为1 
	//优化 
	for(int i=2;i<=N;i++)
	{
		ny[i]=ksm((long long )i);//逆元数组预处理
	}
	int t;
	cin>>t;
	while(t--)
	{
		cin>>n>>m;
		for (int i = 1; i <= n; i++)
		{
            vect[i].clear();//vect数组初始化 
             vis[i] = 0;//vis[]初始化 
		}
		if(n==1)//特判 
		{
			cout<<2<<endl;
			continue;
		}
		for(int i=0;i<m;i++)
		{
			long long int u,v;
			scanf("%d%d",&u,&v);
			vect[u].push_back(v);
		}
		
		dfs(1);
		cout<<dp[1]<<endl;//dp[1]即为所有城市期望和 
		
	}
}


 

 

发布了44 篇原创文章 · 获赞 6 · 访问量 1211

猜你喜欢

转载自blog.csdn.net/qq_43868883/article/details/95478835