P6030-[SDOI2012]走迷宫【高斯消元,tarjan,期望dp】
生活随笔
收集整理的這篇文章主要介紹了
P6030-[SDOI2012]走迷宫【高斯消元,tarjan,期望dp】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題面鏈接:https://www.luogu.com.cn/problem/P6030
題目大意
nnn個點的一張有向圖,求起點到終點的期望步數。保證每個強連通分量大小不超過100100100。
解題思路
顯然如果是強連通分量那么顯然需要用高斯消元。
先把強連通用tarjantarjantarjan縮起來,如果有任何不是ttt的節點沒有出度那么答案都為INFINFINF,然后剩下的每個用高斯消元做一次即可。
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<cmath> #include<stack> using namespace std; const int N=1e4+10; int n,m,s,t,out[N],deg[N],top[N],pos[N]; int cnt,num,col[N],dfn[N],low[N]; double ans[N];bool ins[N]; vector<int> v[N]; stack<int> st; struct Graph{int ls[N],tot;struct node{int from,to,next;}a[N*200];void addl(int x,int y){a[++tot].to=y;a[tot].from=x;a[tot].next=ls[x];ls[x]=tot;return;} }G,D; struct Guass{double a[110][110],b[110];void solve(int n){for(int i=1;i<=n;i++){int z=i;for(int j=i+1;j<=n;j++)if(fabs(a[j][i])>fabs(a[z][i]))z=j;for(int j=1;j<=n;j++)swap(a[i][j],a[z][j]);swap(b[z],b[i]);for(int j=1;j<=n;j++){if(i==j)continue;double rate=a[j][i]/a[i][i];for(int k=i;k<=n;k++)a[j][k]-=rate*a[i][k];b[j]-=rate*b[i];}}for(int i=1;i<=n;i++)b[i]/=a[i][i];return;} }M; void tarjan(int x){dfn[x]=low[x]=++cnt;st.push(x);ins[x]=1;for(int i=G.ls[x];i;i=G.a[i].next){int y=G.a[i].to;if(!dfn[y]){tarjan(y);low[x]=min(low[x],low[y]); }else if(ins[y])low[x]=min(low[x],dfn[y]);}if(dfn[x]==low[x]){++num;while(st.top()!=x){col[st.top()]=num;v[num].push_back(st.top());ins[st.top()]=0;st.pop();}col[st.top()]=num;v[num].push_back(st.top());ins[st.top()]=0;st.pop();}return; } void topsort(){int head=1,tail=1;top[1]=col[s];while(head<=tail){int x=top[head++];for(int i=D.ls[x];i;i=D.a[i].next){int y=D.a[i].to;deg[y]--;if(!deg[y])top[++tail]=y;}}return; } void calc(int id){int cnt=0;for(int i=0;i<v[id].size();i++)pos[v[id][i]]=++cnt;memset(M.a,0,sizeof(M.a));memset(M.b,0,sizeof(M.b));for(int p=0;p<v[id].size();p++){int x=v[id][p];if(!out[x])return;for(int i=G.ls[x];i;i=G.a[i].next){int y=G.a[i].to;if(col[x]!=col[y])M.b[pos[x]]+=1.0*ans[y]/out[x];else M.a[pos[x]][pos[y]]-=1.0/out[x];}M.a[pos[x]][pos[x]]+=1;M.b[pos[x]]+=1;}M.solve(cnt);for(int i=0;i<v[id].size();i++)ans[v[id][i]]=M.b[i+1];return; } int main() {scanf("%d%d%d%d",&n,&m,&s,&t);for(int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);if(x!=t){out[x]++;G.addl(x,y);}}tarjan(s);for(int i=1;i<=G.tot;i++){int x=G.a[i].from,y=G.a[i].to;if(col[x]!=col[y]&&col[x]!=col[t])deg[col[x]]++;}for(int i=1;i<=n;i++){if(i==t&&!dfn[i])return printf("INF\n")&0;if(col[i]!=col[t]&&dfn[i]&&!deg[col[i]])return printf("INF\n")&0;}memset(deg,0,sizeof(deg));for(int i=1;i<=G.tot;i++){int x=G.a[i].from,y=G.a[i].to;if(!col[x]||!col[y]||col[x]==col[t])continue;if(col[x]!=col[y]){D.addl(col[x],col[y]);deg[col[y]]++;}}topsort();for(int i=num;i>=1;i--)calc(top[i]);printf("%.3lf",ans[s]); }總結
以上是生活随笔為你收集整理的P6030-[SDOI2012]走迷宫【高斯消元,tarjan,期望dp】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 哪吒汽车 CEO 张勇:AEB 场景复杂
- 下一篇: 知乎宣布“知海图 AI”大模型将开放服务