poj 3463(dijk贪心思想的应用)

题意是找出最短路径以及比最短路径大一的路径的总的路径条数。。。。。。

贪心思想来求解最短路,并且记录最短和次短,以及出现的次数:

当前长度len 的四个处理:

1. 比最短要小。。。。更新最短和次短

2. 等于最短。。。。。更新最短次数

3. 比次短要小。。。。更新次短

4. 等于次短。。。。。更新次短次数

然后可以用STL的堆或者手写堆也可以。。。。主要是加快效率的。。。。。


#include <iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int M = 1005, inf = 1 << 30;
#define cc(m,v) memset(m,v,sizeof(m))

struct {
    int v, len, next;
} edge[10 * M];
int dis[M][2], cnt[M][2], vis[M][2];
int head[M], k;

struct node {
    int v, flag;

    node(int vv, int f) {
        v = vv, flag = f;
    }
    bool operator<(const node & a) const {
        return dis[v][flag] > dis[a.v][a.flag];
    }
};
priority_queue<node>q;

void addedge(int u, int v, int len) {
    edge[k].v = v, edge[k].len = len, edge[k].next = head[u], head[u] = k++;
}

void dijkstra(int s, int n) {
    int i, v, len;
    cc(cnt, 0), cc(vis, 0);
    for (i = 0; i <= n; i++)
        dis[i][0] = dis[i][1] = inf;
    cnt[s][0] = 1;
    dis[s][0] = 0;
    q.push(node(s, 0));
    while (!q.empty()) {
        node u = q.top();
        q.pop();
        if (vis[u.v][u.flag]) continue;
        vis[u.v][u.flag] = 1;
        for (i = head[u.v]; i != -1; i = edge[i].next) {
            v = edge[i].v, len = dis[u.v][u.flag] + edge[i].len;
            if (len < dis[v][0]) {
                if (dis[v][0] != inf) {
                    dis[v][1] = dis[v][0], cnt[v][1] = cnt[v][0];
                    q.push(node(v, 1));
                }
                dis[v][0] = len, cnt[v][0] = cnt[u.v][u.flag];
                q.push(node(v, 0));
            } else if (len == dis[v][0]) cnt[v][0] += cnt[u.v][u.flag];
            else if (len < dis[v][1]) {
                dis[v][1] = len, cnt[v][1] = cnt[u.v][u.flag];
                q.push(node(v, 1));
            } else if (len == dis[v][1]) cnt[v][1] += cnt[u.v][u.flag];
        }
    }
}

void ainit() {
    k = 0, cc(head, -1);
}

int main(int argc, char** argv) {

    int cas, m, n, s, t, i, j, ans;
    int a, b, c;
    scanf("%d", &cas);
    while (cas--) {
        ainit();
        scanf("%d%d", &n, &m);
        for (i = 1; i <= m; i++) {
            scanf("%d%d%d", &a, &b, &c);
            addedge(a, b, c);
        }
        scanf("%d%d", &s, &t);
        dijkstra(s, n);
        ans = cnt[t][0];
        if (dis[t][0] == dis[t][1] - 1) ans += cnt[t][1];
        printf("%d\n", ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值