P6154 游走

题目链接

题意分析

说实在的 被绿题卡了跟被驴踢了的感觉差不多

不过是概率问题 还是情有可原的捂脸

这道题 说白了 我们假设len是所有路径的长度和 sum是所有路径的数量

那么答案就是(frac{len}{sum})

首先的话 这是一道有向无环图的题 所以我们可以考虑来个拓扑排序

记录两个状态a[i]还有b[i]

a[i]表示所有到i位置的路径长度和

b[i]表示所有到i位置的路径数量(包括起点与终点相同 所以初始化为1)

那么状态转移就是

(a[i]=sum{a[j]+b[j],j→i}) 从j转移到i 所有的路径长度都会+1

(b[i]=sum{b[j],j→i})

CODE:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#define mod 998244353
#define N 1008611
using namespace std;
int n,m,tot;
int to[N],nex[N],head[N];
int in[N];
long long ans1,ans2;
long long cdy[N],wzy[N];
queue<int> que;
long long qpow(long long x,int y)
{long long res=1;for(;y;y>>=1,x=x*x%mod) if(y&1) res=res*x%mod;return res;}
void add(int x,int y)
{to[++tot]=y;nex[tot]=head[x];head[x]=tot;}
void DPsort()
{
	for(int i=1;i<=n;++i) wzy[i]=1LL;
	for(int i=1;i<=n;++i)
	if(!in[i]) que.push(i);
	while(!que.empty())
	{
		int u=que.front();que.pop();
		for(int i=head[u];i;i=nex[i])
		{
			int v=to[i];
			wzy[v]=(wzy[v]+wzy[u])%mod;
			cdy[v]=(cdy[v]+wzy[u]+cdy[u])%mod;
			in[v]--;
			if(!in[v]) que.push(v);
		}
	}
//	for(int i=1;i<=n;++i)
//	printf("%d %d
",cdy[i],wzy[i]);
	for(int i=1;i<=n;++i) 
	ans1=(ans1+cdy[i])%mod,ans2=(ans2+wzy[i])%mod;
	printf("%lld
",ans1*qpow(ans2,mod-2)%mod);
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1,x,y;i<=m;++i)
	{
		scanf("%d%d",&x,&y);
		add(x,y);in[y]++;
	}
	DPsort();
	return 0;
}
原文地址:https://www.cnblogs.com/LovToLZX/p/13957770.html