• bzoj1138


    dp+spfa优化

    最朴素的dp是dp[i][j]表示i->j的最短路,然后把所有pair(i,i)放到队列里跑spfa,但是这样被卡掉了,那么我们要优化一下

    问题在于每次我们转移的时候要枚举i和j的邻居,这样会被两个连起来的菊花卡掉,那么我们希望一次只走一步,那么复杂度会大大降低,于是我们设一个状态g[i][j][k],表示当前在i,j,上一条出边的字符为k,这样我们让f和g交替转移,达到了每次只走一步的目标,然后就能过了,原先每次转移最坏O(m*m)?现在大概是O(n*m)的转移,状态数O(n*n*26)

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 410, inf = 0x3f3f3f3f;
    struct edge {
        int nxt, to, c;
    } e[N * N << 1];
    struct node {
        int u, v, c;
        node(int u, int v, int c) : u(u), v(v), c(c) {}
    };
    int n, m, cnt = 1, q, last;
    int head1[N], head2[N], f[N][N], g[N][N][27], vis[N][N][27];
    void link1(int u, int v, int c)
    {
        e[++cnt].nxt = head1[u];
        head1[u] = cnt;
        e[cnt].to = v;
        e[cnt].c = c;
    }
    void link2(int u, int v, int c)
    {
        e[++cnt].nxt = head2[u];
        head2[u] = cnt;
        e[cnt].to = v;
        e[cnt].c = c;
    }
    void bfs()
    {
        queue<node> q;
        memset(f, inf, sizeof(f));
        memset(g, inf, sizeof(g));
        for(int i = 1; i <= n; ++i) vis[i][i][26] = 1, f[i][i] = 0, q.push(node(i, i, 26));
        for(int i = 1; i <= n; ++i)
            for(int j = 0; j < 26; ++j) vis[i][i][j] = 1, g[i][i][j] = 0, q.push(node(i, i, j));
        while(!q.empty())
        {
            node o = q.front();
            q.pop();
            int u = o.u, v = o.v;
            vis[u][v][o.c] = 0;
            if(o.c == 26)
            {
                for(int i = head1[v]; i; i = e[i].nxt) if(g[u][e[i].to][e[i].c] > f[u][v] + 1)
                {
                    g[u][e[i].to][e[i].c] = f[u][v] + 1;
                    if(!vis[u][e[i].to][e[i].c])
                    {
                        vis[u][e[i].to][e[i].c] = 1;
                        q.push(node(u, e[i].to, e[i].c));
                    }
                }
            }
            else
            {
                for(int i = head2[u]; i; i = e[i].nxt) if(e[i].c == o.c && f[e[i].to][v] > g[u][v][o.c])
                {
                    f[e[i].to][v] = g[u][v][o.c] + 1;
                    if(!vis[e[i].to][v][26])
                    {
                        vis[e[i].to][v][26] = 1;
                        q.push(node(e[i].to, v, 26));
                    }
                }
            }
        }   
    }
    int main()
    {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= m; ++i)
        {
            int u, v;
            char c[2];
            scanf("%d%d%s", &u, &v, c);
            link1(u, v, c[0] - 'a');
            link2(v, u, c[0] - 'a');
        }
        bfs();
        scanf("%d%d", &q, &last);
        q--;
        while(q--)
        {
            int x;
            scanf("%d", &x);
            printf("%d
    ", f[last][x] == inf ? -1 : f[last][x]); 
            last = x;
        }
        return 0;
    } 
    View Code
  • 相关阅读:
    [C++] static member variable and static const member variable
    [C++] const inside class VS const outside class
    [C++] OOP
    [C++] Function Template
    [C++] right value reference
    [C++] advanced reference
    [C++] const and char*
    [C++] c Struct VS c++ Struct
    [C++] decltype(auto) C++ 11 feature
    easyui-validatebox 的简单长度验证
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7549886.html
Copyright © 2020-2023  润新知