正题
题面链接: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]);
}