bzoj1415

记忆化搜索

这是一个dag,肯定会抓住的,所以可以记忆化搜索

然后预处理出p[i][j]表示i,j位置怎么走,记忆化搜索就行了

#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
struct edge {
    int nxt, to;
} e[N << 1];
int n, m, a, b, cnt = 1;
int head[N], d[N][N], p[N][N];
double deg[N], dp[N][N];
void link(int u, int v)
{
    e[++cnt].nxt = head[u];
    head[u] = cnt;
    e[cnt].to = v;
}
double dfs(int a, int b)
{
    if(a == b) return 0;
    if(p[a][b] == b) return 1;
    if(p[a][b] <= n && p[p[a][b]][b] == b) return 1;
    if(dp[a][b] != -1) return dp[a][b];
    int to = p[p[a][b]][b];
    dp[a][b] = (dfs(to, b) + 1.0) / (deg[b] + 1.0);
    for(int i = head[b]; i; i = e[i].nxt) dp[a][b] += (dfs(to, e[i].to) + 1.0) / (deg[b] + 1.0);
    return dp[a][b]; 
}
int main()
{
    scanf("%d%d%d%d", &n, &m, &a, &b);
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= n; ++j) dp[i][j] = -1.0;
    for(int i = 1; i <= m; ++i)
    {
        int u, v;
        scanf("%d%d", &u, &v);
        link(u, v);
        link(v, u);
        deg[u] += 1.0;
        deg[v] += 1.0; 
    }
    memset(p, 0x3f3f, sizeof(p));
    memset(d, -1, sizeof(d));
    for(int i = 1; i <= n; ++i)
    {       
        d[i][i] = 0;
        queue<int> q;
        q.push(i);
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            for(int j = head[u]; j; j = e[j].nxt) if(d[i][e[j].to] == -1)
            {
                d[i][e[j].to] = d[i][u] + 1;
                q.push(e[j].to);
            }
        }
        for(int j = 1; j <= n; ++j)
        {
            int mn = 0x3f3f3f3f;
            for(int k = head[j]; k; k = e[k].nxt) 
            {
                if(mn > d[i][e[k].to])
                {
                    mn = d[i][e[k].to];
                    p[j][i] = e[k].to;
                }
                else if(mn == d[i][e[k].to]) p[j][i] = min(p[j][i], e[k].to);
            }
        }
    }
    printf("%.3f
", dfs(a, b));
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/19992147orz/p/7659955.html