zoukankan      html  css  js  c++  java
  • BZOJ2707: [SDOI2012]走迷宫

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2707

    首先找出所有强联通分量然后缩点,然后从开始点的那个联通块开始dfs,如果发现它走到了死路,那么期望步数就是无限大。

    然后判断掉无限大的情况后我们对每个scc求期望,对于scc中的每个点,由E[u]=ΣE[v]*1/d[u]+1,联立方程高斯消元。(如果连边连到scc外,就让常数项加上E[x]/d[u])

    注意E[t]=0,然后要把t的所有出边全部砍掉。但是建方程的时候其系数还要是1。。。

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<stack>
    #include<cstring>
    #define rep(i,l,r) for (int i=l;i<=r;i++)
    #define down(i,l,r) for (int i=l;i>=r;i--)
    #define clr(x,y) memset(x,y,sizeof(x))
    #define maxm 1005000
    #define maxn 105000
    #define eps 1e-6
    using namespace std;
    stack<int >q;
    struct data{int obj,pre;
    }e[maxm];
    int head[maxn],low[maxn],dfn[maxn],vis[maxn],num[maxn],d[maxn],size[maxn],rank[maxn],cal[maxn];
    int b[maxn][205];
    double a[205][205],ex[maxn];
    int idx,tot,scc,n,m,s,t;
    int read(){
        int x=0,f=1; char ch=getchar();
        while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
        while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    void insert(int x,int y){
        e[++tot].obj=y; e[tot].pre=head[x]; head[x]=tot;
    }
    void tarjan(int u){
        dfn[u]=low[u]=++idx; q.push(u);
        for (int j=head[u];j;j=e[j].pre){
            int v=e[j].obj;
            if (!dfn[v]){
                tarjan(v); 
                low[u]=min(low[u],low[v]);
            }
            else if (!num[v]) low[u]=min(low[u],dfn[v]);
        }
        if (low[u]==dfn[u]){
            int x=-1,cnt=0; ++scc;
            while (x!=u){
                x=q.top(); q.pop();
                num[x]=scc;
                rank[x]=++cnt;
                size[scc]++;
                b[scc][size[scc]]=x;
            }
        }
    }
    void dfs(int x){
        vis[x]=0;
        if (x==num[t]){
            vis[x]=1; return ;
        }
        rep(i,1,size[x]){
            int u=b[x][i];
            for (int j=head[u];j;j=e[j].pre){
                int v=e[j].obj;
                if (num[v]==x) continue;
                if (vis[num[v]]==-1) dfs(num[v]);
                if (vis[num[v]]==1) vis[x]=1; 
            }
        }    
    }
    void gs(int n){
        int x;
        rep(i,1,n){
            x=i; while (fabs(a[x][i])<eps&&x<=n) x++;
             if (x>n) continue;
             rep(j,1,n+1) swap(a[i][j],a[x][j]);
             double t=a[i][i];
             rep(j,1,n+1) a[i][j]/=t;
             rep(j,1,n) if (j!=i){
                 double t=a[j][i];
                 rep(k,1,n+1) a[j][k]-=t*a[i][k];
             }
        }
    }
    void solve(int x){
        rep(i,1,size[x]){
            int u=b[x][i];
            for (int j=head[u];j;j=e[j].pre){
                int v=e[j].obj;
                if (num[v]!=x&&!cal[num[v]]) solve(num[v]); 
            }
        }
        clr(a,0);
        rep(i,1,size[x]){
            a[i][i]=1.0;
            int u=b[x][i]; 
            if (u==t) continue;
            a[i][size[x]+1]=1.0;
            for (int j=head[u];j;j=e[j].pre){
                int v=e[j].obj;
                if (num[v]==x) a[i][rank[v]]-=1.0/d[u];
                else a[i][size[x]+1]+=1.0/d[u]*ex[v]; 
            }
        }
        gs(size[x]);
        rep(i,1,size[x]) ex[b[x][i]]=a[rank[b[x][i]]][size[x]+1];
        cal[x]=1; 
    }
    int main(){
        n=read(); m=read(); s=read(); t=read();
        if (s==t){
            puts("0.000"); return 0;
        }
        rep(i,1,m){
            int x,y;
            x=read(); y=read(); insert(x,y); d[x]++;
        }
        rep(i,1,n){
            if (!dfn[i]) tarjan(i);
        }
        
        clr(vis,-1);
        dfs(num[s]);
        rep(i,1,scc) if (vis[i]==0) {
            puts("INF"); return 0;
        }
        
        solve(num[s]);
        printf("%.3lf
    ",ex[s]);
        return 0;
    }
  • 相关阅读:
    0421 & SX2016
    HDU3948 & 回文树模板
    BZOJ 2152 & 点分治
    HDU5618 & CDQ分治
    CC countari & 分块+FFT
    ECF R9(632E) & FFT
    ECF R9(632E) & DP
    BZOJ的两道osu概率DP easy与osu
    BZOJ3197 & 组合乱搞
    转载 Rational Rose 的配置和破解
  • 原文地址:https://www.cnblogs.com/ctlchild/p/5008435.html
Copyright © 2011-2022 走看看