【jzoj2758】【SDOI2012】【走迷宫】【期望】【高斯消元】
2017-06-24 08:42
351 查看
题目大意
Morenan 被困在了一个迷宫里。迷宫可以视为 N 个点 M 条边的有向图,其中 Morena n处于起点 S , 迷宫的终点设为 T 。 可惜的是 , Morenan 非常的脑小 , 他只会从一个点出发随机沿着一条从该点出发的有向边 , 到达另一个点 。 这样 , Morenan 走的步数可能很长 , 也可能是无限,更可能到不了终点。 若到不了终点,则步数视为无穷大。 但你必须想方设法求出 Morenan 所走步数的期望值。
解题思路
倒着求到终点的期望,按拓扑序求,将所有强连通分量求出来缩点,分量内使用高斯消元求解即可。如果有一条路径不能到达终点即输出inf。
code
#include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #define LF double #define LL long long #define ULL unsigned long long #define fo(i,j,k) for(int i=j;i<=k;i++) #define fd(i,j,k) for(int i=j;i>=k;i--) #define fr(i,j) for(int i=begin[j];i;i=next[i]) #define f2(i,j) for(int i=begi2[j];i;i=nex2[i]) using namespace std; int const mn=1e4+9,mm=1e6+9,mp=100+9,inf=1e9+7; int n,m,s,t,gra,time,begin[mn],to[mm],next[mm],gr2,begi2[mn],t2[mm],nex2[mm], dfn[mn],low[mn],inst[mn],st[mn],bel[mn],b[mn],d2[mn],u[mm],v[mm],beg[mn], end[mn],du[mn],q[mn],tag[mn],re[mn]; LF f[mn],a[mp][mp],a2[mp]; void insert(int u,int v){ to[++gra]=v; next[gra]=begin[u]; begin[u]=gra; } void inser2(int u,int v){ t2[++gr2]=v; nex2[gr2]=begi2[u]; begi2[u]=gr2; } void tarjan(int now){ dfn[now]=low[now]=++time; inst[st[++st[0]]=now]=1; fr(i,now)if(!dfn[to[i]]){ tarjan(to[i]); low[now]=min(low[now],low[to[i]]); }else if(inst[to[i]])low[now]=min(low[now],dfn[to[i]]); if(dfn[now]==low[now]){ while(st[st[0]]!=now)bel[st[st[0]]]=now,inst[st[st[0]--]]=0; bel[st[st[0]]]=now,inst[st[st[0]--]]=0; } } void dfs(int now){ tag[now]=1; fr(i,now)if(!tag[to[i]])dfs(to[i]); } bool cmp(int x,int y){ return bel[x]<bel[y]; } void solve(int l,int r){ int n=r-l+1; fo(i,1,n)fo(j,1,n+1)a[i][j]=0; fo(i,l,r){ int now=b[i]; a[i-l+1][i-l+1]=1;a[i-l+1][n+1]=1; fr(j,now)if(bel[now]==bel[to[j]]) a[i-l+1][re[to[j]]-l+1]+=-1.0/d2[now]; else a[i-l+1][n+1]+=f[to[j]]/d2[now]; } fo(i,1,n){ if(!a[i][i]){ fo(j,i+1,n)if(a[j][i]) fo(k,i,n+1)swap(a[i][k],a[j][k]); } fo(j,i+1,n){ LF tmp=a[j][i]/a[i][i]; fo(k,i,n+1)a[j][k]-=a[i][k]*tmp; } } fd(i,n,1){ a2[i]=a[i][n+1]; fo(j,i+1,n)a2[i]-=a[i][j]*a2[j]; a2[i]/=a[i][i]; } fo(i,l,r)f[b[i]]=a2[i-l+1]; } int main(){ freopen("d.in","r",stdin); freopen("d.out","w",stdout); scanf("%d%d%d%d",&n,&m,&s,&t); int tmp=0; fo(i,1,m){ tmp++; scanf("%d%d",&u[tmp],&v[tmp]); if(u[tmp]==t){tmp--;continue;} insert(u[tmp],v[tmp]);d2[u[tmp]]++; } m=tmp; fo(i,1,n)if(!dfn[i])tarjan(i); fo(i,1,n)b[i]=i; sort(b+1,b+n+1,cmp); fo(i,1,n)re[b[i]]=i; int i=1; while(i<=n){ int j=i; while(bel[b[i]]==bel[b[j]])j++; beg[bel[b[i]]]=i; end[bel[b[i]]]=j-1; i=j; } fo(i,1,m)if(bel[u[i]]!=bel[v[i]])inser2(bel[u[i]],bel[v[i]]),du[bel[v[i]]]++; int he=0,ti=0,ok=1; fo(i,1,n)if((bel[i]==i)&&(!du[i]))q[++ti]=i; dfs(s); while(he!=ti){ int now=q[++he],tmp=ti; f2(i,now)if((--du[t2[i]])==0)q[++ti]=t2[i]; if((!begi2[now])&&(now!=bel[t]))ok=0; } fd(i,ti-1,1) solve(beg[q[i]],end[q[i]]); if(tag[t]&&ok)printf("%.3lf\n",f[s]-f[t]); else printf("INF"); //fo(i,1,n)printf("%.10lf\n",f[i]); return 0; }
相关文章推荐
- bzoj 2707: [SDOI2012]走迷宫 (高斯消元+概率期望+tarjan缩点+拓扑序)
- 【BZOJ2707】[SDOI2012]走迷宫 Tarjan+拓扑排序+高斯消元+期望
- [BZOJ]2707: [SDOI2012]走迷宫 期望+高斯消元
- BZOJ 2707: [SDOI2012]走迷宫 拓扑+高斯消元+期望概率dp+Tarjan
- bzoj 2707: [SDOI2012]走迷宫 期望dp+强连通分量+高斯消元
- 2707: [SDOI2012]走迷宫 tarjan+高斯消元解期望方程组
- BZOJ 2707: [SDOI2012]走迷宫 [高斯消元 scc缩点]
- [BZOJ2707][SDOI2012]走迷宫(tarjan+概率期望+高斯消元)
- bzoj2707[SDOI2012]走迷宫 关于一类图上有环线性动态规划与高斯消元的问题研究
- BZOJ.2707.[SDOI2012]走迷宫(期望 Tarjan 高斯消元)
- 【JLOI 2012】时间流逝(期望,树上高斯消元)
- bzoj 2707: [SDOI2012]走迷宫(Trajan+高斯消元+Dp)
- bzoj 2707 [SDOI2012]走迷宫(SCC+高斯消元)
- 【jzoj3221】【HNOI2013】【游走】【高斯消元】【期望】
- BZOJ 2707: [SDOI2012]走迷宫( tarjan + 高斯消元 )
- 【JZOJ2758】【SDOI2012】走迷宫(labyrinth)
- BZOJ 4820 [Sdoi2017]硬币游戏 ——期望DP 高斯消元
- 【jzoj3282】【GDOI2013】【飞行棋】【期望】【高斯消元】
- BZOJ2707 [SDOI2012]走迷宫 【概率dp + tarjan + 高斯消元】
- HDU - 2262 Where is the canteen 高斯消元求期望(浮点数)