日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

P6030-[SDOI2012]走迷宫【高斯消元,tarjan,期望dp】

發布時間:2023/12/3 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。