DP - 打望

Posted lrw04

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DP - 打望相关的知识,希望对你有一定的参考价值。

题面

【问题描述】

Mr_he 是一个求变的人,所以每天从学校机房回到家都要走不同的路径,当然劳累一天然后漫步 在新鲜的大路上,打望过往行人和车辆也是一件非常惬意的事。 那么现在已经知道,从Mr_he 的学校到家有n 个交叉路口,把他们从1..n 编号,我们认为编 号为1 的是学校,编号为2 的为家,有m 条双向大路把这些路口连接起来。 Mr_he 打算每天沿着一条不同的路径回家(如果两条路径有一条道路不同,那么我们认为这两条 路径是不同的),欣赏不同的风景。但他不想太晚回家,因此他不打算走“回头路”。换句话说,他只 沿着满足如下条件的道路(A,B)走:存在一条从B 出发回家的路径比所有从A 出发回家的路径都短。 那么你的任务是帮助Mr_he 计算一共有多少条不同的回家路径。

【输入格式】

  • 第一行为n,m,交叉点的数目和道路的数目。

  • 以下 m 行每行 3 个整数:a,b,d(1≤a,b≤n,1≤d≤1000000),表示有一条连接a 和b 的双向道路,长度为d。

【输出格式】

输出路径条数。这个数可能很大,请输出 mod 20080814 的结果。

【输入样例】

5 6
1 3 2
1 4 2
3 4 3
1 5 12
4 2 34
5 2 24

【输出样例】

2

【数据范围】

  • 20%的数据:1<n≤10

  • 50%的数据:1<n≤100

  • 100%的数据:1<n≤1000,n-1≤m≤100000

重读题目,意即寻找从机房到家,结点到家的最短路程递减的路径条数。那么可以用 Dijkstra 得出所有节点到家的最短路程,再 DP 得出从机房开始的这样的路径条数。

程序

#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
typedef long long ll;

#define MAXN 1020
#define MAXM 200020

int to[MAXM], nxt[MAXM], hd[MAXN], ne = 0;
ll val[MAXM];

int n, m;

void _link(int u, int v, ll w) {
    nxt[++ne] = hd[u];
    hd[u] = ne;
    to[ne] = v;
    val[ne] = w;
}

void link(int u, int v, ll w) {
    _link(u, v, w);
    _link(v, u, w);
}

ll dist[MAXN];
bool vis[MAXN];

struct HeapNode {
    int u;
    ll d;
    HeapNode(int u=0, ll d=0): u(u), d(d) {}
    bool operator<(const HeapNode& rhs) const {
        return d > rhs.d;
    }
};

void dijkstra(int s) {
    priority_queue<HeapNode> q;
    memset(vis, false, sizeof(vis));
    memset(dist, 0x3f, sizeof(dist));
    dist[s] = 0;
    q.push(HeapNode(s, 0));
    while (!q.empty()) {
        int u = q.top().u;
        q.pop();
        if (vis[u]) continue;
        vis[u] = true;
        for (int i = hd[u]; i; i = nxt[i]) {
            int v = to[i]; ll w = val[i];
            if (dist[u] + w < dist[v]) {
                dist[v] = dist[u] + w;
                q.push(HeapNode(v, dist[v]));
            }
        }
    }
}

#define MOD 20080814

int d[MAXN];

int dp(int u) {
    if (d[u] > -1) return d[u];
//  cerr << "	" << u << endl;
    int ans = 0;
    bool flg = true;
    for (int i = hd[u]; i; i = nxt[i])
        if (dist[to[i]] < dist[u]) {
            ans = (ans + dp(to[i])) % MOD;
            flg = false;
        }
    if (flg) ans = 1;
    return d[u] = ans;
}

int main() {
    cin >> n >> m;
    for (int i = 0; i < m; i++) {
        int u, v;
        ll w;
        cin >> u >> v >> w;
        link(u, v, w);
    }
    dijkstra(2);
//  for (int i = 1; i <= n; i++) cerr << dist[i] << " "; cerr << endl;
    memset(d, -1, sizeof(d));
    cout << dp(1) << endl;
//  for (int i = 1; i <= n; i++) cerr << d[i] << " "; cerr << endl;
    return 0;
}

以上是关于DP - 打望的主要内容,如果未能解决你的问题,请参考以下文章

1024. 视频拼接 dp

POJ3691DNA repair(AC自动机,DP)

HDU4057 Rescue the Rabbit(AC自动机+状压DP)

HDU3247 Resource Archiver(AC自动机+BFS+DP)

[bzoj1966][Ahoi2005][VIRUS 病毒检测] (字符串dp)

18.06.03 POJ 4126:DNA 15年程设期末05(状压DP)