UVA 10917 最短路

UVA 10917

题目链接:

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=&problem=1858&mosmsg=Submission+received+with+ID+16031317

题意:

一个图,问有多少种不同的方案从点2走到点1。选路的要求是,对于一条路A-B,若A存在一条路回家比任何从B出发回家的路都短,则可以走该路。

思路:

最短路+DAG_Dp

值得注意的是,A-B不一定是最后构成的最短路上的边。

终于搞清楚大白书上Dijkstra为什么要重复入队列了。因为对于当前节点u,可能下一次遍历时得到更优的距离值d[u],在优先队列中会上升到更前面的位置。这时候就需要把它重复的压到队列里面。这里WA了无数。

然而Bellman-Ford不存在这样的问题,因为它算法设计的本身就会重复入列。自己做的时候把Dijkstra改成Bellman_Ford就过了。

源码:

Dijikstra

#include <cstdio>

#include <cstring>

#include <cmath>

#include <cstdlib>

#include <algorithm>

#include <iostream>

#include <vector>

#include <queue>

#include <stack>

using namespace std;

#define inf (1000000007)

const int MAXN = 1000 + 5;

int n, m;

int head[MAXN], cnt;

struct Edge

{

    int v, val;

    int ne;

    Edge(){}

    Edge(int _u, int _v, int _val){v = _v, val = _val, ne = head[_u];}

}edge[MAXN*MAXN*2];

void add_edge(int u, int v, int val)

{

    edge[cnt] = Edge(u, v, val);

    head[u] = cnt++;

}

struct D

{

    int d, u;

    bool operator < (const D &rbs)const

    {

        return d > rbs.d;

    }

};

priority_queue<D>que;

int d[MAXN], vis[MAXN];

void dijkstra(int s)

{

    for(int i = 1 ; i <= n ; i++)

        d[i] = inf, vis[i] = 0;

    d[s] = 0;

    while(!que.empty()) que.pop();

    que.push(D{d[s], s});

    while(!que.empty()){

        int org = que.top().u;  que.pop();

        if(vis[org])    continue;

        vis[org] = 1;

        for(int now = head[org] ; now != -1 ; now = edge[now].ne){

            int v = edge[now].v;

            if(d[v] > d[org] + edge[now].val){

                d[v] = d[org] + edge[now].val;

                que.push(D{d[v], v});

            }

        }

    }

}

int dp[MAXN];

void dfs(int u)

{

//    printf("u = %d\n", u);

    if(dp[u] != -1)

        return;

    dp[u] = 0;

    for(int now = head[u] ; now != -1 ; now = edge[now].ne){

        int v = edge[now].v;

        if(d[u] > d[v])

            dfs(v), dp[u] += dp[v];

    }

}

int main()

{

//    freopen("UVA 10917.in", "r", stdin);

    while(scanf("%d", &n) != EOF && n){

        scanf("%d", &m);

        int u, v, val;

        cnt = 0;

        memset(head, -1, sizeof(head));

        for(int i = 1 ; i <= m ; i++){

            scanf("%d%d%d", &u, &v, &val);

            add_edge(u, v, val);

            add_edge(v, u, val);

        }

        dijkstra(2);

        for(int i = 1 ;i <= n ; i++)

            dp[i] = -1;

        dp[2] = 1;

        dfs(1);

        printf("%d\n", dp[1]);

    }

}

Bellman_Ford

#include <cstdio>

#include <cstring>

#include <cmath>

#include <algorithm>

#include <iostream>

#include <queue>

#include <cstdlib>

#include <stack>

#include <vector>

using namespace std;

#define MOD (2147483647)

#define LL long long

#define inf (1000000007)

const int MAXN = 1000 + 5;

int head[MAXN], cnt;

struct Edge

{

    int u, v, val;

    int ne;

    Edge(){}

    Edge(int _u, int _v, int _val){u = _u, v = _v, val = _val, ne = head[u];}

}edge[MAXN * MAXN * 2];

void addedge(int u, int v, int val)

{

    edge[cnt] = Edge(u, v, val);

    head[u] = cnt++;

}

int n, m;

int dp[MAXN];

int dis[MAXN];

queue<int>q;

struct D

{

    int u;

    D(){}

    D(int _u){u = _u;}

    bool operator < (const D &rbs)const

    {

        return dis[u] > dis[rbs.u];

    }

};

vector<int>path[MAXN], lv[MAXN];

priority_queue<D>que;

int vis[MAXN], in[MAXN];

void dijkstra()

{

    memset(in, 0, sizeof(in));

    for(int i = 1 ; i <= n ; i++)

        dis[i] = inf, path[i].clear();

    dis[2] = 0;

    in[2] = 1;

    while(!que.empty()) que.pop();

    que.push(D(2));

    while(!que.empty()){

        int org = que.top().u;  que.pop();

        int now = head[org];

        in[org] = 0;

        while(now != -1){

            int u = org;

            int v = edge[now].v, val = edge[now].val;

            if(dis[v] > dis[u] + val){

//                path[v].clear();

//                path[v].push_back(u);

                dis[v] = dis[u] + val;

                if(in[v] == 0) in[v] = 1, que.push(D(v));

            }

//            else if(dis[v] == dis[u] + val)

//                path[v].push_back(u);

            now = edge[now].ne;

        }

    }

//    printf("dp\n");

//    for(int i = 1 ; i <= n ; i++)

//        printf("%d ", dp[i]);

//    printf("\n");

//    printf("dp\n");

}

void dfs(int u)

{

    if(dp[u] != -1)

        return;

    dp[u] = 0;

    for(int now = head[u] ; now != -1 ; now = edge[now].ne){

        int v = edge[now].v;

//        printf("u = %d, v = %d\n", u, v);

        if(dis[v] < dis[u]){

            dfs(v); dp[u] += dp[v];

        }

    }

}

int main()

{

//    freopen("UVA 10917.in", "r", stdin);

    while(scanf("%d", &n) != EOF && n){

        scanf("%d", &m);

        cnt = 0;

        memset(head, -1, sizeof(head));

        int u, v, val;

        for(int i = 1 ; i <= m ; i++){

            scanf("%d%d%d", &u, &v, &val);

//            printf("%d %d %d\n", u, v, val);

            addedge(u, v, val);

            addedge(v, u, val);

        }

        dijkstra();

//        for(int i = 1 ; i <= n ; i++){

//            lv[i].clear();

//            in[i] = 0;

//        }

//        for(int i = 1 ; i <= n ; i++){

//            for(int j = 0 ; j < (int)path[i].size() ; j++){

//                int u = path[i][j];

//                int v = i;

//                lv[u].push_back(v);

//                in[v]++;

//            }

//        }

//        printf("path\n");

//        for(int i = 1 ; i <= n ; i++){

//            printf("u = %d, v =  ", i);

//            for(int j = 0 ; j < (int)lv[i].size() ; j++)

//                printf(" %d ", lv[i][j]);

//            printf("\n");

//        }

//        printf("path\nlv\n");

//        for(int i = 1 ; i <= n ; i++){

//            printf("u = %d, v =  ", i);

//            for(int j = 0 ; j < (int)lv[i].size() ; j++)

//                printf(" %d ", lv[i][j]);

//            printf("\n");

//        }

//        printf("lv\n");

        memset(dp, -1, sizeof(dp));

        dp[2] = 1;

        dfs(1);

        printf("%d\n", dp[1]);

    }

    return 0;

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值