• [NOIP 2017] 逛公园


    [题目链接]

             http://uoj.ac/problem/331

    [算法]

            首先,我们预处理出每个点到第N个点的最短路,这等价于在反图上求第N个点到其余点的最短路

            然后,我们用f[u][k]表示从第u个点到第n个点,至多走长度为dist(u,n) + k的路径有多少种走法

            记忆化搜索即可,注意判断是否存在0环

    [代码]

            

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 100010
    #define MAXM 200010
    #define MAXK 55
    const int INF = 2e9;
    
    int i,j,tot,ans,u,v,w,T,N,M,K,P;
    int head[MAXN],rhead[MAXN],dist[MAXN];
    int f[MAXN][MAXK];
    bool visited[MAXN][MAXK];
    bool flag;
    
    struct Edge
    {
            int to,w,nxt;
    } e[MAXM << 1];
    
    inline void addedge(int u,int v,int w)
    {
            tot++;
            e[tot] = (Edge){v,w,head[u]};
            head[u] = tot;
            tot++;
            e[tot] = (Edge){u,w,rhead[v]};
            rhead[v] = tot;
    }
    inline void dijkstra(int s)
    {
            int i,v,w,cur;
            priority_queue< pair<int,int> > q;
            static bool visited[MAXN];
            while (!q.empty()) q.pop();
            for (i = 1; i <= N; i++)
            {
                    dist[i] = INF;
                    visited[i] = false;
            }
            dist[s] = 0;
            q.push(make_pair(0,s));
            while (!q.empty())
            {
                    cur = q.top().second;
                    q.pop();
                    if (visited[cur]) continue;
                    visited[cur] = true;
                    for (i = rhead[cur]; i; i = e[i].nxt)
                    {
                            v = e[i].to;
                            w = e[i].w;
                            if (dist[cur] + w < dist[v])
                            {
                                    dist[v] = dist[cur] + w;
                                    q.push(make_pair(-dist[v],v));
                            }
                    }
            }
    }
    inline int dp(int now,int k)
    {
            int i,v,w,tmp,cnt,ret;
            if (f[now][k] != -1) return f[now][k];
            if (now == N) ret = 1;
            else ret = 0;
            if (visited[now][k]) return -1;
            visited[now][k] = true;
            for (i = head[now]; i; i = e[i].nxt)
            {
                    v = e[i].to;
                    w = e[i].w;
                    tmp = k - (dist[v] + w - dist[now]);
                    if (tmp < 0) continue;
                    cnt = dp(v,tmp);
                    if (cnt == -1) 
                    {
                            flag = true;
                            return -1;
                    } else ret = (ret + cnt) % P;
            }    
            visited[now][k] = false;
            return f[now][k] = ret;
    }
    
    int main() 
    {
            
            scanf("%d",&T);
            while (T--)
            {
                    scanf("%d%d%d%d",&N,&M,&K,&P);
                    tot = 0;
                    for (i = 1; i <= N; i++) head[i] = rhead[i] = 0;
                    for (i = 1; i <= M; i++)
                    {
                            scanf("%d%d%d",&u,&v,&w);
                            addedge(u,v,w);
                    }        
                    dijkstra(N);
                    flag = false;
                    for (i = 1; i <= N; i++)
                    {
                            for (j = 0; j <= K; j++)
                            {
                                    f[i][j] = -1;
                                    visited[i][j] = false;
                            }
                    }
                    ans = dp(1,K);
                    if (flag) printf("-1
    ");
                    else printf("%d
    ",ans);
            }
            
            return 0;
        
    }
  • 相关阅读:
    在浏览器地址栏输入URL,按下回车后究竟发生了什么?
    企业内部DNS跨国配置案例
    Cobbler批量部署CentOS
    入侵检测工具之RKHunter & AIDE
    SSH服务端配置、优化加速、安全防护
    数据传输的加密过程
    mysql怎么让一个存储过程定时执行
    MYSQL中replace的用法
    eclipse 插件
    MySQL定时执行脚本(计划任务)命令实例
  • 原文地址:https://www.cnblogs.com/evenbao/p/9359287.html
Copyright © 2020-2023  润新知