poj 3463 Sightseeing

Description:

给出一张无向图,求最短路以及次短路条数之和。

 

思路:次短路什么的真的不是很会啊。看了别人的题解,然后发现可以用堆里面可以用一个三元组存储点的编号,距离,以及1和0分别表示最短路和次短路,然后跑的时候转移状态即可

#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
const int N = 1010, M = 10040, INF = 1e9;
struct node{
    int u, d;
    bool f;
    bool operator < (const node& a)const{
        return d > a.d;
    }
};
int n, m, s, e, dp[N][2], dis[N][2];
bool vis[N][2];

int head[N], now;
struct edges{
    int to, next, w;
}edge[M<<1];
void add(int u, int v, int w){ edge[++now] = {v, head[u], w}; head[u] = now;}

void dij(int s,int e){
    memset(dis, 0x3f, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    priority_queue<node> heap;
    dis[s][0] = 0;
    heap.push((node){s, dis[s][0], 0});
    dp[s][0] = 1;
    while(!heap.empty()){
        node tmp = heap.top(); heap.pop();
        int x = tmp.u, flag = tmp.f;
        if(vis[x][flag]) continue;
        vis[x][flag] = 1;
        for(int i = head[x]; i; i = edge[i].next){
            int v = edge[i].to, temp = edge[i].w + dis[x][flag];
            if(temp < dis[v][0]){
                if(dis[v][0] < INF){
                    dis[v][1] = dis[v][0];
                    dp[v][1] = dp[v][0];
                    heap.push((node){v, dis[v][1], 1});
                }
                dis[v][0] = temp;
                dp[v][0] = dp[x][flag];
                heap.push((node){v, dis[v][0], 0});
            }
            else if(temp == dis[v][0])
              dp[v][0] += dp[x][flag];
            else if(temp < dis[v][1]){
                dis[v][1] = temp;
                dp[v][1] = dp[x][flag];
                heap.push((node){v, dis[v][1], 1});
            }
            else if(temp == dis[v][1])
              dp[v][1] += dp[x][flag];
        }
    }
    return ;
}
void init(){
    memset(dis, 0 ,sizeof(dis));
    memset(dp, 0, sizeof(dp));
    memset(edge,0,sizeof(edge));
    memset(head,0,sizeof(head)); now = 0;
}
int main(){
    int T; 
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        init();
        int x, y, z;
        for(int i = 1; i <= m; i++){
            scanf("%d%d%d",&x, &y, &z);
            add(x, y, z);
        }
        scanf("%d%d",&s, &e);
        dij(s, e);
        if(dis[e][1] - dis[e][0] == 1) printf("%d\n", dp[e][0] + dp[e][1]);
        else printf("%d\n", dp[e][0]);
    //    printf("%d\n", dis[e][1]);
    }
    return 0;
}
View Code

 

posted @ 2018-04-05 23:02  Ror_shach  阅读(165)  评论(0编辑  收藏  举报