bzoj2707 [SDOI2012] maze

Posted by rkrass on Sat, 04 Apr 2020 03:46:13 +0200

Description

Morenan was trapped in a maze. Maze can be regarded as a digraph with N points and M edges, where morenan is at the starting point S and the end of maze is set as T. Unfortunately, morenan'S brain is very small. He can only start from one point and randomly follow a directed edge from that point to another point. In this way, morenan may take a long step, or it may be infinite, or it may not reach the end. If the destination is not reached, the number of steps is regarded as infinite. But you have to figure out how many steps morenan takes.

N<=10000
M<=1000000
Ensure that the size of strongly connected components does not exceed 100
In addition, 40% of the data is evenly distributed. There is no ring or self ring in the graph

Solution

Let's not talk about rings. If a given graph is dag, it's good to recurs it
Now add the ring limit and shrink it
It is found that the ring is very small, so the Gauss elimination in the ring is enough. Between the ring and the ring, the calculated variables are regarded as constants to cover the elimination

The yardage is not enough. I think it's zhizhang who wrote for 2 hours+

Code

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <stack>
#include <vector>

#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define drp(i,st,ed) for (int i=st;i>=ed;--i)
#define fill(x,t) memset(x,t,sizeof(x))

const int N=40005;
const int E=2000005;

struct edge {int x,y,next;} e[E];
std:: stack <int> stack;
// std:: vector <int> rec[N];

double a[205][205],ans[N];
int in[N],_in[N],out[N],d[N];
int dfn[N],low[N],bel[N];
int queue[N],head=1,tail=0;
int ls[N],edCnt,tot;
int rec[N][205],pos[N];
bool vis[N],flag=false;

void addEdge(int x,int y) {
    e[++edCnt]=(edge) {x,y,ls[x]};
    ls[x]=edCnt; in[y]++; out[x]+=(x!=y); d[x]++;
}

void dfs(int now) {
    dfn[now]=low[now]=++tot;
    stack.push(now); vis[now]=1;
    for (int i=ls[now];i;i=e[i].next) {
        if (!dfn[e[i].y]) {
            dfs(e[i].y);
            low[now]=std:: min(low[now],low[e[i].y]);
        } else if (vis[e[i].y]) {
            low[now]=std:: min(low[now],dfn[e[i].y]);
        }
    }
    if (low[now]==dfn[now]) {
        bel[0]++;
        for (int tmp=0;tmp!=now;) {
            tmp=stack.top(); stack.pop();
            bel[tmp]=bel[0];
            vis[tmp]=0;
            rec[bel[0]][++rec[bel[0]][0]]=tmp;
        }
    }
}

void gauss(int n) {
    rep(i,1,n) {
        int l=i;
        rep(j,i+1,n) if (fabs(a[j][i])>fabs(a[l][i])) l=j;
        if (l!=i) std:: swap(a[i],a[l]);
        double tmp=a[i][i];
        rep(j,1,n+1) a[i][j]/=tmp;
        rep(j,1,n) {
            if (i!=j&&a[j][i]) {
                tmp=a[j][i];
                rep(k,1,n+1) a[j][k]-=a[i][k]*tmp;
            }
        }
    }
}

void calc(int x) {
    fill(a,0); int size=rec[x][0];
    rep(i,1,size) pos[rec[x][i]]=i;
    rep(ti,1,size) {
        int now=rec[x][ti];
        if (!d[now]) return ;
        for (int i=ls[now];i;i=e[i].next) {
            if (bel[e[i].x]==bel[e[i].y]) {
                a[pos[now]][pos[e[i].y]]+=1.0/(double)d[now];
            } else {
                a[pos[now]][size+1]-=1.0*ans[e[i].y]/(double)d[now];
            }
        }
        a[pos[now]][size+1]-=1.0;
        a[pos[now]][pos[now]]+=-1.0;
    }
    gauss(size);
    rep(i,1,size) ans[rec[x][i]]=a[i][size+1];
}

void top_sort(int n) {
    memcpy(_in,in,sizeof(in));
    rep(i,1,n) {
        if (in[i]==0) {
            queue[++tail]=i;
        }
    }
    while (head<=tail) {
        int now=queue[head++];
        rep(j,1,rec[now][0]) {
            for (int i=ls[rec[now][j]];i;i=e[i].next) {
                if (bel[e[i].x]==bel[e[i].y]) continue;
                if (!(--in[bel[e[i].y]])) {
                    queue[++tail]=bel[e[i].y];
                }
            }
        }
    }
    memcpy(in,_in,sizeof(in));
    drp(ti,n,1) {
        int now=queue[ti] ;
        calc(now);
    }
}

void tarjan(int n,int st,int ed) {
    dfs(st);
    rep(i,1,n) {
        if (i!=ed&&dfn[i]&&!out[i]) {
            puts("INF");
            flag=true;
            return ;
        }
        if (i==ed&&!dfn[i]) {
            puts("INF");
            flag=true;
            return ;
        }
    }
    fill(in,0); fill(out,0);
    rep(i,1,edCnt) {
        if (bel[e[i].x]!=bel[e[i].y]&&bel[e[i].x]&&bel[e[i].y]) {
            in[bel[e[i].y]]++;
            out[bel[e[i].x]]++;
        }
    }
}

int main(void) {
    freopen("data.in","r",stdin);
    freopen("myp.out","w",stdout);
    int n,m,st,ed; scanf("%d%d%d%d",&n,&m,&st,&ed);
    rep(i,1,m) {
        int x,y; scanf("%d%d",&x,&y);
        if (x!=ed) addEdge(x,y);
    }
    tarjan(n,st,ed);
    if (flag) return 0;
    top_sort(bel[0]);
    rep(i,1,n)
    printf("%.3lf\n", ans[i]);
    return 0;
}