计算最短路和次短路条数

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1688

题意:在给定有向图中查找最短路与次短路,如果(最短路+1==次短路)则输出(最短路条数+次短路条数),否则只输出最短路条数。

思路:在最短路的松弛操作上做些判断和记录即可,具体看代码吧(有注释)。

#include<iostream>
#include<cstdio>
#include<queue>
#include<string>
#include<string.h>
#include<map>
#include<vector>
#include<algorithm>
#include<cmath>
#include<iterator>
#define mem(a,b) memset(a,b,sizeof(a))
#define MOD 100000007
#define LL long long
#define INF 0x3f3f3f3f
const double pi = acos(-1.0);
const int Maxn=50000;
using namespace std;
inline int scan()
{
    int x=0,c=1;
    char ch=' ';
    while((ch>'9'||ch<'0')&&ch!='-')ch=getchar();
    while(ch=='-')c*=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
    return x*c;
}
int tol;
int head[1000*2];
/*******************前向星存边**************************/ 
struct edge{
    int to,next,w;
}e[10000*2];
void add(int start,int ed,int w){
    e[tol].to=ed;
    e[tol].w=w;
    e[tol].next=head[start];
    head[start]=tol++;
}
/******************优先队列优化 **************************/ 
struct node{
    int start;
    int w,p;
    node(int start,int w,int p):start(start),w(w),p(p){}
    friend bool operator < (node a,node b){
        return a.w>b.w;
    }
};
priority_queue<node>Q;
int cnt[2][1010];
int dis[2][1010];
bool vis[2][1010];
void dij(int start,int ed){
    dis[0][start]=0;//最短路的起点距离初始化为0 
    cnt[0][start]=1;//最短路因为一定会有一条,所以更新为一 
    Q.push(node(start,0,0));
    while(!Q.empty()){
        node n2=Q.top();
        Q.pop();
        int p=n2.p;
        int s=n2.start;
        if(vis[p][s]) continue;//如果该状态下的以s为起点已经松弛过就不要再进行操作了,会影响结果 
        vis[p][s]=true;
        for(int i=head[s];i!=-1;i=e[i].next){
            int to=e[i].to;
            int w=e[i].w;
            if(dis[0][to]>dis[p][s]+w){//如果这条边会使从s到to变短,则更新s到to的最短路与次短路以及他们的条数 
                
                dis[1][to]=dis[0][to];//原先的最短路变成了次短路 
                dis[0][to]=dis[p][s]+w;//更新最短路 
                cnt[1][to]=cnt[0][to];//原先最短路条数变成次短路条数 
                cnt[0][to]=cnt[p][s];//更新最短路条数 
                Q.push(node(to,dis[0][to],0));//用这个s->to当前最短路去更新其他的路 
                Q.push(node(to,dis[1][to],1));//同上 
                
            }else if(dis[0][to]==dis[p][s]+w){//这条路径等于当前s->to最短路,则s->to最短路条数增加即可 
                
                cnt[0][to]+=cnt[p][s];
            
            }else if(dis[1][to]>dis[p][s]+w){//当前路径的路径长度大于最短路但是小于次短路//更新次短路即可 
                
                dis[1][to]=dis[p][s]+w;
                cnt[1][to]=cnt[p][s];
                Q.push(node(to,dis[1][to],1));
                
            }else if(dis[1][to]==dis[p][s]+w){//同上 
                
                cnt[1][to]+=cnt[p][s];
                
            }
        }
    }
}
int n,m;
/********************************初始化*******************************/ 
void clear(){
    tol=0;
    for(int i=0;i<=n;i++){
        dis[0][i]=dis[1][i]=INF*2;
    }
    mem(head,-1);
    mem(cnt,0);
    mem(vis,false);
    mem(e,0);
    while(!Q.empty()) Q.pop();
}
/*************************************main函数*****************************/ 
int main(){
    std::ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--){
        int start,ed,w;
        cin>>n>>m;
        clear();
        for(int i=0;i<m;i++){
            cin>>start>>ed>>w;
            add(start,ed,w);
        }
        int s,f;
        cin>>s>>f;
        dij(s,f);
//        cout<<dis[0][f]<<"  "<<dis[1][f]<<endl;
//        cout<<cnt[0][f]<<"  "<<cnt[1][f]<<endl;
        int ans=cnt[0][f];
        if(dis[0][f]+1==dis[1][f]){
            ans+=cnt[1][f];
        }
        cout<<ans<<endl;
    }
    return 0;
}

 

posted @ 2019-04-15 20:08  Choose_and_be_chosen  阅读(327)  评论(0编辑  收藏  举报