POJ 3462(最短路 + 次最短路, 路径条数)

题目链接: http://poj.org/problem?id=3463

题意:给定一张有向图,以及起点 s   终点 f, 求从 s 到 f 的最短路的路径条数 以及 比最短路径大1 的路径条数   之和

思路: 用A*算法,类似求第K短路 来写    超时。就只能求最短路 与 次最短路的路径长度以及 它们各自的条数。

求次最短路类似于求次最大值。

AC代码:

#include<cstdio>
#include<queue>
#include<cstring>
#include<vector>
using namespace std;

const int maxn = 1010;
vector<pair<int,int> >E[maxn];
int d[maxn][2];                 ///d[i][0] 表示最短  d[i][1] 表示次最短
int cnt[maxn][2];               ///cnt[i][0] 表示最短的条数,   cnt[i][1] 表示 次最短的条数
int vis[maxn][2];
struct node{
    int v;
    int flag;
    node(){}
    node(int v,int flag):v(v),flag(flag){}
    friend bool operator < (const node &A,const node &B){
        return d[A.v][A.flag] > d[B.v][B.flag];
    }
};

void init(){
    for(int i = 0;i < maxn;i ++){
        E[i].clear();
        d[i][0] = d[i][1] = 1e9;
        cnt[i][0] = cnt[i][1] = 0;
        vis[i][0] = vis[i][1] = 0;
    }
}

int dijsktra(int s,int f){
    d[s][0] = 0;
    cnt[s][0] = 1;
    priority_queue<node>Q;
    Q.push(node(s,0));
    while(!Q.empty()){
        int v = Q.top().v;
        int flag = Q.top().flag;
        Q.pop();
        if(vis[v][flag]) continue;          ///因为要多次Q.push() , 可能会放入重复的点
        vis[v][flag] = 1;
        for(int i = 0;i < E[v].size();i ++){
            int to = E[v][i].first;
            int dis = d[v][flag] + E[v][i].second;
            if(d[to][0] > dis){
                if(d[to][0] != 1e9){
                    d[to][1] = d[to][0];
                    cnt[to][1] = cnt[to][0];
                    Q.push(node(to,1));
                }
                d[to][0] = dis;
                cnt[to][0] = cnt[v][flag];
                Q.push(node(to,0));
            }
            else if(d[to][0] == dis){
                cnt[to][0] += cnt[v][flag];
            }
            else if(d[to][1] > dis){
                d[to][1] = dis;
                cnt[to][1] = cnt[v][flag];
                Q.push(node(to,1));
            }
            else if(d[to][1] == dis){
                cnt[to][1] += cnt[v][flag];
            }
        }
    }
    if(d[f][0] + 1 == d[f][1])
        return cnt[f][0] + cnt[f][1];
    return cnt[f][0];
}

int main()
{
    int t; scanf("%d",&t);
    while(t--){
        init();
        int n ,m; scanf("%d%d",&n,&m);
        int A,B,L;
        for(int i = 0;i < m;i ++){
            scanf("%d%d%d",&A,&B,&L);
            E[A].push_back(make_pair(B,L));
        }
        int s,f; scanf("%d%d",&s,&f);
        printf("%d\n",dijsktra(s,f));
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值