• [SDOI2012] 走迷宫


    前言

    吐了,这东西能出一万个锅。

    题目

    洛谷

    DarkBZOJ

    讲解

    随机游走考虑高斯消元,结合强连通分量大小不超过 (100) 可以推测是对强连通分量进行高斯消元。

    先考虑无解情况:从 (S) 走到一个无法到达 (T) 的点。

    其实并不好做,稍微转化一下:如果存在一个 (S) 可以不经过 (T) 到达的点,但从 (T) 出发在反图上无法到达,即无解。

    然后我们缩点,按拓扑序倒序做高斯消元,这样可以保证一个强连通分量连到外面的点的期望已经求出。

    而这个拓扑序倒序其实就是我们求出强连通分量的顺序,所以直接做即可。

    时间复杂度 (O(100^3(frac{n}{100})+m)=O(10^4n+m)),上限是 (10^8),可以过。

    代码

    自认为比较优美的代码
    //12252024832524
    #include <bits/stdc++.h>
    #define TT template<typename T>
    using namespace std;
    
    typedef long long LL;
    const int MAXN = 10005;
    const int MAXM = 1000005;
    int n,m,S,T;
    int ID[MAXN];
    
    LL Read()
    {
    	LL x = 0,f = 1; char c = getchar();
    	while(c > '9' || c < '0'){if(c == '-') f = -1;c = getchar();}
    	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
    	return x * f;
    }
    TT void Put1(T x)
    {
    	if(x > 9) Put1(x/10);
    	putchar(x%10^48);
    }
    TT void Put(T x,char c = -1)
    {
    	if(x < 0) putchar('-'),x = -x;
    	Put1(x); if(c >= 0) putchar(c);
    }
    TT T Max(T x,T y){return x > y ? x : y;}
    TT T Min(T x,T y){return x < y ? x : y;}
    TT T Abs(T x){return x < 0 ? -x : x;}
    
    int head[MAXN],tot,rtot,rhead[MAXN];
    struct edge
    {
    	int v,nxt;
    }e[MAXM],re[MAXM];
    void Add_Edge(int &t,edge *E,int *hd,int x,int y)
    {
    	E[++t] = edge{y,hd[x]};
    	hd[x] = t;
    }
    
    bool xvis[MAXN];
    void xinei(int x)
    {
    	xvis[x] = 1;
    	if(x == T) return;
    	for(int i = head[x]; i ;i = e[i].nxt) if(!xvis[e[i].v]) xinei(e[i].v);
    }
    bool nvis[MAXN];
    void neixi(int x)
    {
    	nvis[x] = 1;
    	for(int i = rhead[x]; i ;i = re[i].nxt) if(!nvis[re[i].v]) neixi(re[i].v);
    }
    bool ins[MAXN];
    int s[MAXN],tl,dfn[MAXN],low[MAXN],dfntot,scc,bl[MAXN],deg[MAXN];
    vector<int> p[MAXN];
    void Tarjan(int x)
    {
    	dfn[x] = low[x] = ++dfntot;
    	s[++tl] = x; ins[x] = 1;
    	for(int i = head[x],v; i ;i = e[i].nxt)
    	{
    		v = e[i].v;
    		if(!dfn[v]) Tarjan(v),low[x] = Min(low[x],low[v]);
    		else if(ins[v]) low[x] = Min(low[x],dfn[v]);
    	}
    	if(low[x] == dfn[x])
    	{
    		int v; ++scc;
    		do
    		{
    			v = s[tl--];
    			ins[v] = 0;
    			bl[v] = scc;
    			p[scc].emplace_back(v);
    		}while(v^x);
    	}
    }
    double a[105][105],dp[MAXN];
    void Gauss(int N)
    {
    	for(int i = 1;i <= N;++ i)
    	{
    		int now = i;
    		for(int j = i+1;j <= N;++ j) if(Abs(a[j][i]) > Abs(a[now][i])) now = j;
    		if(i ^ now) swap(a[i],a[now]);
    		for(int j = 1;j <= N;++ j)
    		{
    			if(i == j) continue;
    			double mu = a[j][i] / a[i][i];
    			for(int k = i;k <= N+1;++ k) a[j][k] -= mu * a[i][k];
    		}
    	}
    }
    
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	n = Read(); m = Read(); S = Read(); T = Read();
    	for(int i = 1,u,v;i <= m;++ i) //之前以为是加边的问题,所以手动实现了函数Add_Edge
    	{
    		u = Read(),v = Read();
    		e[++tot] = edge{v,head[u]}; head[u] = tot;
    		re[++rtot] = edge{u,rhead[v]}; rhead[v] = rtot;
    		++deg[u];
    	}
    	xinei(S); neixi(T);
    	for(int i = 1;i <= n;++ i) if(xvis[i] && !nvis[i]) {printf("INF
    ");return 0;}
    	Tarjan(S);
    	for(int sc = 1;sc <= scc;++ sc) 
    	{
    		int N = 0;
    		for(auto x : p[sc]) ID[x] = ++N,a[N][N] = 1;
    		for(auto x : p[sc])
    		{
    			if(x^T) a[ID[x]][N+1] = 1;
    			else continue;
    			for(int i = head[x],v; i ;i = e[i].nxt)
    			{
    				v = e[i].v;
    				if(bl[v] ^ bl[x]) a[ID[x]][N+1] += 1.0 / deg[x] * dp[v];
    				else a[ID[x]][ID[v]] += -1.0 / deg[x];
    			}
    		}
    		Gauss(N);
    		for(int i = 1;i <= N;++ i) dp[p[sc][i-1]] = a[i][N+1] / a[i][i];
    		for(int i = 1;i <= N;++ i)
    			for(int j = 1;j <= N+1;++ j)
    				a[i][j] = 0;
    	}
    	printf("%.3f
    ",dp[S]);
    	return 0;
    }
    
  • 相关阅读:
    关于xcode4.0调试出现“EXE_BAD_ACCESS”错误的处理
    UITableView 使用2
    mysql 命令行导入大的sql文件
    XCode4.0 内存监控方法
    如何在iphone app中加入google跟踪代码
    JQuery Mobile表单元素样式
    H.265编码视频播放器EasyPlayerProWIN版播放HLS协议视频流显示时间与实际不符如何修复?
    Visual Studio 2017自建WebRTC中peerconnection_client程序编译报错的解决方法
    【开发记录】TSINGSEE青犀视频开发H265播放器时销毁播放器仍不断重连地址如何修复
    TSINGSEE青犀视频云边端架构视频平台HLS视频流内m3u8文件和TS切片是什么关系?
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/15431206.html
Copyright © 2020-2023  润新知