带权最短路计数,洛谷1608

upd:之前的博客什么也没讲,只贴了代码,居然能在百度搜素的第一条,我表示抱歉,,,,,,

 

考虑dijstra的过程,最短路计数我们只需要加上一个ans,如果当前能松弛,即dis[v]>dis[u]+e[i].w,我们就讲当前v的ans更新为ans[u],但还有一种特殊情况即dis[v]=dis[u]+e[i].w,我们此时需要将方案数累加,即ans[v]+=ans[u]

 

然后此题需要判断重边,就做完了

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define re register int
#define ll long long
#define inf 0x3f3f3f3f
#define maxn 2000050
using namespace std;
struct tu{
    int u,v,w,nxt;
}e[maxn<<1];
int head[maxn],cnt;
void add(int u,int v,int w){
    e[++cnt].u=u;
    e[cnt].v=v;
    e[cnt].w=w;
    e[cnt].nxt=head[u];
    head[u]=cnt;
}
int chong[2005][2005];
int dis[maxn];
bool vis[maxn];
int n,m;
ll ans[maxn];
priority_queue<pair<int,int> >q;
void dijstra(){
    memset(dis,inf,sizeof(dis));
    
    dis[1]=0;
    ans[1]=1;
    q.push(make_pair(0,1));
    while(q.size()){    
    int u=q.top().second;
    q.pop();
    if(vis[u])continue;
    vis[u]=1;
    for(re i=head[u];i;i=e[i].nxt){
        int v=e[i].v;
    
        if(dis[v]>dis[u]+e[i].w){
            dis[v]=dis[u]+e[i].w;
            q.push(make_pair(-dis[v],v));
            ans[v]=ans[u];
        }
        else if(dis[v]==dis[u]+e[i].w){
            ans[v]=ans[v]+ans[u];
        }
    }
    
    
}
}
signed main(){
    scanf("%d%d",&n,&m);
    for(re i=1;i<=m;i++){
        int a1,a2,a3;
        scanf("%d%d%d",&a1,&a2,&a3);
           if(!chong[a1][a2])
           add(a1,a2,a3),chong[a1][a2]=cnt;
        else {
            if(e[chong[a1][a2]].w>a3)e[chong[a1][a2]].w=a3; 
        }
           
    }
    dijstra();

        if(dis[n]==inf)printf("No answer\n");
        else printf("%d %lld\n",dis[n],ans[n]);
    
    
    return 0;
}

 

posted @ 2019-06-04 08:38  红色OI再临  阅读(283)  评论(0编辑  收藏  举报