zoukankan      html  css  js  c++  java
  • 【JZOJ2758】【SDOI2012】走迷宫(labyrinth)

    ╰( ̄▽ ̄)╭

    Morenan 被困在了一个迷宫里。
    迷宫可以视为 N 个点 M 条边的有向图,其中 Morena n处于起点 S , 迷宫的终点设为 T 。
    可惜的是 , Morenan 非常的脑小 , 他只会从一个点出发随机沿着一条从该点出发的有向边 , 到达另一个点 。
    这样 , Morenan 走的步数可能很长 , 也可能是无限,更可能到不了终点。
    若到不了终点,则步数视为无穷大。
    但你必须想方设法求出 Morenan 所走步数的期望值。

    (⊙ ▽ ⊙)

    一开始看着道题,就觉得是tarjan缩点后,转化成DAG上的问题。

    当原图是DAG时
    

    fi表示第i个点走到终点的距离。
    容易有fi=jnext(i)1|next(i)|(fj+1)
    其中next(i)i的后继集合。
    很容易使用拓扑排序来完成动态规划。

    当原图是一般的有向图时
    

    利用tarjan算法可以把图中的强连通分量找出来。
    对于任意一个强连通分量,我们利用高斯消元来求解出强连通分量中的每个点的f值。
    套上拓扑排序,就能够解决。


    时间复杂度为O(nL3),其中L为最大强连通分量的大小。
    实际时间复杂度则远远不到。

    ( ̄~ ̄)

    高斯(gauss)消元:

    1.目标
    

    nn元一次方程求解。

    2.步骤
    

    首先:
    把某条方程的第一个元的系数化为一,利用它可以消去其他方程的第一元。
    以此类推,可以消去第二个元、第三个元……
    最后,会只剩下一条只关于最后一元的方程,实际上就是这一元的根。
    然后:
    得出最后一元的根后,就可以代入先前的方程。
    于是可以算出所有元的根。

    (⊙v⊙)

    #include<iostream>
    #include<algorithm>
    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #define ll long long
    using namespace std;
    const char* fin="jzoj2758.in";
    const char* fout="jzoj2758.out";
    const int Inf=0x7fffffff;
    const int maxn=20007,maxm=2000007,maxk=107;
    int n,m,St,En,i,j,k,N,ti;
    int fi[maxn],ne[maxm],la[maxm],tot;
    int Fi[maxn],Ne[maxm],La[maxm],Tot;
    int dfn[maxn],low[maxn],num,st[maxn],be[maxn];
    bool bz[maxn],End;
    int inf[maxn];
    int az[maxn];
    int ha[maxn][maxk],ru[maxn],id[maxn],tow[maxn];
    double f[maxn],gs[maxk][maxk];
    int b[maxn],head,tail;
    void add_line(int a,int b){
        tot++;
        ne[tot]=fi[a];
        la[tot]=b;
        fi[a]=tot;
    }
    void Add_line(int a,int b){
        Tot++;
        Ne[Tot]=Fi[a];
        La[Tot]=b;
        Fi[a]=Tot;
    }
    void tarjan(int v){
        int i,j,k;
        dfn[v]=low[v]=++num;
        bz[st[j=++st[0]]=v]=true;
        for (k=fi[v];k;k=ne[k])
            if (!dfn[la[k]]){
                tarjan(la[k]);
                low[v]=min(low[v],low[la[k]]);
            }else if (bz[la[k]]) low[v]=min(low[la[k]],low[v]);
        if (low[v]==dfn[v]){
            N++;
            be[N]=0;
            while (st[0]>=j){
                ha[N][++ha[N][0]]=st[st[0]];
                be[st[st[0]]]=N;
                bz[st[st[0]--]]=false;
            }
        }
    }
    double ABS(double x){
        return x>0?x:-x;
    }
    void add(int v){
        b[++tail]=v;
    }
    void count(int v,int n){
        int i,j,k,l;
        double tmp,tmd;
        ti++;
        for (i=1;i<=n-1;i++){
            for (j=1;j<n;j++){
                if (az[j]<ti && (gs[j][i]>10e-13 || gs[j][i]<-10e-13)){
                    az[j]=ti;
                    tow[i]=j;
                    tmp=1.0/gs[j][i];
                    for (k=1;k<=n;k++) gs[j][k]*=tmp;
                    for (k=1;k<n;k++){
                        if (k==j) continue;
                        tmd=gs[k][i];
                        for (l=1;l<=n;l++)
                            gs[k][l]-=tmd*gs[j][l];
                    }
                    break;
                }
            }
        }
        for (i=n-1;i>=1;i--){
            f[ha[v][tow[i]]]=-gs[tow[i]][n];
            for (j=1;j<=n-1;j++){
                gs[j][n]-=gs[j][i]*gs[tow[i]][n];
            }
        }
    }
    void work(int v){
        int i,j,k;
        for (i=1;i<=ha[v][0];i++) id[ha[v][i]]=i;
        for (i=1;i<=ha[v][0];i++){
            for (j=1;j<=ha[v][0]+1;j++) gs[i][j]=0;
            j=0;
            for (k=Fi[ha[v][i]];k;k=Ne[k]){
                gs[i][ha[v][0]+1]+=1;
                gs[i][i]-=1;
                if (f[La[k]]>10e-7 || La[k]==En) gs[i][ha[v][0]+1]+=f[La[k]];
                else gs[i][id[La[k]]]+=1;
            }
        }
        count(v,ha[v][0]+1);
    }
    void update(int v){
        int i,j,k;
        for (i=1;i<=ha[v][0];i++)
            for (k=fi[ha[v][i]];k;k=ne[k]){
                inf[be[la[k]]]=max(inf[be[la[k]]],inf[v]);
                if (!--ru[be[la[k]]]) add(be[la[k]]);
            }
    }
    void topsort(){
        int i,j,k;
        head=tail=0;
        memset(f,0,sizeof(f));
        f[En]=0;
        for (i=n+1;i<=N;i++)
            if (!ru[i]){
                add(i);
            }
        while (head++<tail){
            if (be[En]==b[head]) inf[b[head]]=1;
            if (inf[b[head]]==0) inf[b[head]]=2;
            if (inf[b[head]]==1 && b[head]!=be[En]) work(b[head]);
            update(b[head]);
        }
    }
    int main(){
        scanf("%d%d%d%d",&n,&m,&St,&En);
        N=n;
        for (i=1;i<=m;i++){
            scanf("%d%d",&j,&k);
            if (j!=En){
                Add_line(j,k);
                add_line(k,j);
            }
        }
        for (i=1;i<=n;i++) if (!dfn[i]) tarjan(i);
        for (i=1;i<=n;i++)
            for (k=fi[i];k;k=ne[k])
                if (be[la[k]]!=be[i]) ru[be[la[k]]]++;
        topsort();
        //printf("%3.lf",f[St]);
        if (inf[be[St]]!=1) printf("INF");
        else printf("%.3lf",f[St]);
        return 0;
    }
  • 相关阅读:
    MVC是什么意思?
    Paypal 在线支付接口应用从零开始,第2节,[支付API原理及流程]
    人人网
    百度框计算研究
    最近总被黑。然后。。发现了很多知识值得学习。。分享出来。
    首次购房契税下调至1% 首付降为20%
    由“百鸡问题”浅谈程序性能
    10月1日起机动车所有人可自行编排车牌号
    08中国互联网大会23在南京开幕
    MySQL联合创始人向Sun递交辞呈
  • 原文地址:https://www.cnblogs.com/hiweibolu/p/6714797.html
Copyright © 2011-2022 走看看