1415: [Noi2005]聪聪和可可

来源:互联网 发布:淘宝无节操买家秀图片 编辑:程序博客网 时间:2024/05/17 22:34

概率dp题,一开始想高斯消元,后来发现无环,但还是只会n^3的DP。
这类题目无环的题,把答案作为dp值记忆化后直接降为n^2+m * n,这是一个实用的技巧,下次遇到这类题目就别想消元了。

%:pragma GCC optimize(3)#include<bits/stdc++.h>using namespace std;const int N = 1005;const int M = N * 5;int pos[N][N] , dis[N][N] , n , m , to[M] , ne[M] , cnt , fir[N] , du[N] , s  , t , x , y , pre[N];double dp[N][N];bool vis[N][N];#define Foreachson(i,x) for(int i = fir[x];i;i = ne[i])void add(int x ,int y) {    ne[++ cnt] = fir[x]; fir[x] = cnt; to[cnt] = y;}void link(int x ,int y) {    add(x,y); add(y,x);    du[x] ++; du[y] ++;}void BFS(int x) {    queue<int>q;    dis[x][x] = 0;    memset(pre,0,sizeof(pre));    Foreachson(i,x) {        int V = to[i];        dis[x][V] = 1;        pre[V] = V;        q.push(V);    }    while(!q.empty()) {        int ind = q.front(); q.pop();        Foreachson(i,ind) {            int V = to[i];            if(dis[x][V] > dis[x][ind] + 1) {                dis[x][V] = dis[x][ind] + 1;                pre[V] = pre[ind];                q.push(V);            }            else if(dis[x][V] == dis[x][ind] + 1) {                if(pre[V] > pre[ind]) {                    pre[V] = pre[ind];                    q.push(V);                }            }        }    }    for(int i = 1;i <= n;i ++) {        pos[x][i] = pre[i];    }    pos[x][x] = x;}double dfs(int x ,int y) {    if(vis[x][y]) return dp[x][y];//  vis[x][y] = 1;    if(x == y) return 0;    if(dis[x][y] <= 2) return 1;    vis[x][y] = 1;    Foreachson(i,y) {        int V = to[i];        dp[x][y] = dp[x][y] + (double)1 / (double)(du[y] + 1) * dfs(pos[pos[x][y]][y] , V);    }    int V = y;    dp[x][y] += (double)1 / (double)(du[y] + 1) * (dfs(pos[pos[x][y]][y] , V));    dp[x][y] += 1.0;    return dp[x][y];}int main(){    scanf("%d%d",&n,&m);    scanf("%d%d",&s,&t);    for(int i = 1;i <= m;i ++) {        scanf("%d%d",&x,&y);        link(x,y);    }    memset(dis,127,sizeof(dis));    for(int i = 1;i <= n;i ++) BFS(i);    printf("%.3lf",dfs(s,t));}
原创粉丝点击