最短路径统计

noip2017 考了这个
不过比这个不知道高到哪里去了
但是毕竟可以用这个混到30分的呀.....

做法

大致有两种做法,可以spfa,也可以写dijkstra
重要的地方都差不多,即用一个数组cnt[ i ] 表示 dis[ i ]有多少种走法

实现

dijkstra很好想,每次都是走的最短路直接更新即可
spfa因为可能会反复进队,所以直接累加会导致重复计算。
很美妙的做法是 每次出队就把 cnt[ k ] 赋成0

题目可以做一下 luogu 1608

代码

dijkstra:

#include <bits/stdc++.h>
using namespace std;
#define maxn 2010
#define inf 1e9

int mp[maxn][maxn],dis[maxn],n,m,c[maxn],cnt,p[maxn];
int read(int x=0){scanf("%d",&x);return x;}
bool vis[maxn];

struct node{
    int a,b,w,nt;
}e[maxn*maxn*2];

inline void add(int x,int y,int z){
    e[++cnt].a=x,e[cnt].b=y,e[cnt].w=z;
    e[cnt].nt=p[x];p[x]=cnt;
}

inline void dijkstra(){
    priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
    for(int i=1;i<=n;i++)dis[i]=inf;
    dis[1]=0;c[1]=1;
    q.push(make_pair(dis[1],1));
    while(!q.empty()){
        pair<int,int> node=q.top();q.pop();
        int k=node.second;
        if(vis[k])continue;vis[k]=true;
        for(int i=p[k];i;i=e[i].nt){
            int kk=e[i].b;
            if(dis[kk]==dis[k]+e[i].w)
                c[kk]+=c[k];
            else if(dis[kk]>dis[k]+e[i].w)
                c[kk]=c[k],dis[kk]=dis[k]+e[i].w,q.push(make_pair(dis[kk],kk));
        }
    }
}

int main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)mp[i][j]=-1;
    for(int i=1;i<=m;i++){
        int a=read(),b=read(),c=read();
        mp[a][b]=mp[a][b]==-1?c:min(c,mp[a][b]);
    }
    for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
        if(mp[i][j]!=-1)add(i,j,mp[i][j]);
    dijkstra();
    if(dis[n]==inf)puts("No answer");
    else printf("%d %d",dis[n],c[n]);
    return 0;
}

spfa:

#include <bits/stdc++.h>
using namespace std;
#define maxn 2010
#define inf 1e9

int mp[maxn][maxn],dis[maxn],n,m,c[maxn];
int read(int x=0){scanf("%d",&x);return x;}
bool vis[maxn];

inline void spfa(){
    queue<int>q;
    for(int i=1;i<=n;i++)dis[i]=inf;
    dis[1]=0;c[1]=1;q.push(1);
    while(!q.empty()){
        int k=q.front();q.pop();vis[k]=false;
        if(k==n)continue;
        for(int kk=1;kk<=n;kk++)if(mp[k][kk]!=-1){
            if(dis[kk]==dis[k]+mp[k][kk])c[kk]+=c[k];
            if(dis[kk]>dis[k]+mp[k][kk])
                dis[kk]=dis[k]+mp[k][kk],c[kk]=c[k];
            if(c[kk]&&!vis[kk])vis[kk]=true,q.push(kk);
        }
        c[k]=0;
    }
}

int main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)mp[i][j]=-1;
    for(int i=1;i<=m;i++){
        int a=read(),b=read(),z=read();
        mp[a][b]=mp[a][b]==-1?z:min(mp[a][b],z);
    }
    spfa();
    if(c[n]==0)puts("No answer");
    else printf("%d %d",dis[n],c[n]);
    return 0;
}
posted @ 2017-11-25 09:27  Tyw_ei  阅读(327)  评论(0编辑  收藏  举报