https://pintia.cn/problem-sets/994805342720868352/problems/994805523835109376

不使用链式前向星,使用邻接矩阵

时间:4 ms

#include <bits/stdc++.h>
#define bug(x) cout<<":x="<<x<<endl;
#define FF(a,b) for(int a=0;a<b;a++)
#define EN 1000
#define VN 500
#define INF (1<<30)-1

using namespace std;

int N,M;
int vw[500];    //点权
int dist[VN];
int pre[VN];
int vis[VN];
int pathc[VN];  //最短路条数
int max_vw[VN];   //最大点权
int g[VN][VN];

void dijkstra(int s,int e){
    pathc[s]=1;
    FF(i,N){
        dist[i]=INF;
        pre[i]=-1;
    }
    dist[s]=0;
    max_vw[s]=vw[s];
    while(1){
        int u=-1,min_d=INF;
        FF(i,N) if(!vis[i] && dist[i]<min_d) {
                min_d=dist[i];
                u=i;
            }
        if(u<0) break;
        vis[u]=1;   //找到最近点,加入S集
        FF(i,N)
            if(!vis[i] && g[u][i]){
                if(dist[i] > dist[u]+g[u][i]) { //s->i > s->u->i
                    pre[i] = u;
                    dist[i] = dist[u] + g[u][i];
                    pathc[i] = pathc[u];
                    max_vw[i]=max_vw[u]+vw[i];
                }
                else if(dist[i]==dist[u]+g[u][i]){
                    pathc[i] += pathc[u];
                    if(max_vw[u]+vw[i] > max_vw[i]){
                        pre[i] = u;
                        dist[i] = dist[u] + g[u][i];
                        max_vw[i]=max_vw[u]+vw[i];
                    }
                }
            }
    }
    printf("%d %d\n",pathc[e],max_vw[e]);
    FF(i,N){
        cout<<dist[i]<<endl;
    }
}

int main(){
    freopen("../in","r",stdin);
    int c1,c2;
    scanf("%d%d%d%d",&N,&M,&c1,&c2);
    FF(i,N){
        int t;
        scanf("%d",&t);
        vw[i]=t;
    }
    FF(i,M){
        int a,b,w;
        scanf("%d%d%d",&a,&b,&w);
        g[a][b]=w;
        g[b][a]=w;
    }
    dijkstra(c1,c2);
}
使用链式前向星, 不堆优化

时间:3 ms

#include <bits/stdc++.h>
#define bug(x) cout<<":x="<<x<<endl;
#define FF(a,b) for(int a=0;a<b;a++)
#define EN 2000
#define VN 500
#define INF (1<<30)-1

using namespace std;

int N,M;
int vw[500];    //点权
int dist[VN];
int pre[VN];
int vis[VN];
int pathc[VN];  //最短路条数
int max_vw[VN];   //最大点权
int g[VN][VN];

int head[EN];    //记录源点u在mp中第一个地址i=head[u] 调用完之后就可以用mp[i]访问边表mp
int cnt=0;        //边表下标,随着数据的录入而扩张
struct edge{    //边
    int to,next,w;
};
edge mp[EN*2];    //边表
void add(int u,int v,int w){    //增加边
    mp[cnt].to=v;
    mp[cnt].w=w;
    mp[cnt].next=head[u];    //指向源点u所构成的静态链表的头结点。如果是首次构造链,head[u]=-1 ,相当于NULL
    head[u]=cnt++;            //更新当前地址
}
void init_mp(){
    fill(head,head+EN,-1);
}

void dijkstra(int s,int e){
    pathc[s]=1;
    max_vw[s]=vw[s];
    FF(i,N){
        dist[i]=INF;
        pre[i]=-1;
    }
    dist[s]=0;
    while(1){
        int u=-1,min_d=INF;
        FF(i,N) if(!vis[i] && dist[i]<min_d) {
                min_d=dist[i];
                u=i;
            }
        if(u<0) break;
        vis[u]=1;   //找到最近点,加入S集
        for(int i=head[u];~i;i=mp[i].next){
            int to=mp[i].to;
            if(!vis[to]){
                if(dist[to] > dist[u]+mp[i].w) { //s->to > s->u->to
                    dist[to] = dist[u] + mp[i].w;
                    pre[to]=u;
                    pathc[to] = pathc[u];
                    max_vw[to]=max_vw[u]+vw[to];
                }else if(dist[to]==dist[u]+mp[i].w){
                    pathc[to] += pathc[u];
                    if(max_vw[u]+vw[to] > max_vw[to]){
                        pre[to]=u;
                        dist[to] = dist[u] + mp[i].w;
                        max_vw[to]=max_vw[u]+vw[to];
                    }
                }
            }
        }
    }
    printf("%d %d\n",pathc[e],max_vw[e]);
}

int main(){
    init_mp();
    freopen("../in","r",stdin);
    int c1,c2;
    scanf("%d%d%d%d",&N,&M,&c1,&c2);
    FF(i,N){
        int t;
        scanf("%d",&t);
        vw[i]=t;
    }
    FF(i,M){
        int a,b,w;
        scanf("%d%d%d",&a,&b,&w);
        add(a,b,w);
        add(b,a,w);
        g[a][b]=g[b][a]=w;
    }
    dijkstra(c1,c2);
}
链式前向星+堆优化

时间:11 ms

#include <bits/stdc++.h>
#define FF(a,b) for(int a=0;a<b;a++)
#define EN 2000
#define VN 500
#define INF (1<<30)-1

using namespace std;

int N,M;
int vw[500];    //点权
int dist[VN];
int pre[VN];
int vis[VN];
int pathc[VN];  //最短路条数
int max_vw[VN];   //最大点权
int g[VN][VN];

//---------------------链式前向星----------------------------
int head[EN];    //记录源点u在mp中第一个地址i=head[u] 调用完之后就可以用mp[i]访问边表mp
int cnt=0;        //边表下标,随着数据的录入而扩张
struct edge{    //边
    int to,next,w;
};
edge mp[EN*2];    //边表
void add(int u,int v,int w){    //增加边
    mp[cnt].to=v;
    mp[cnt].w=w;
    mp[cnt].next=head[u];    //指向源点u所构成的静态链表的头结点。如果是首次构造链,head[u]=-1 ,相当于NULL
    head[u]=cnt++;            //更新当前地址
}
void init_mp(){
    fill(head,head+VN,-1);
}
//---------------------链式前向星----------------------------

//---------------------堆优化----------------------------
struct cmp{
    bool operator () (int a,int b){
        return dist[a]>dist[b];
    }
};
priority_queue<int,vector<int>,cmp> pq;
//---------------------堆优化----------------------------


void dijkstra(int s,int e){
    fill(dist,dist+N,INF);
    fill(pre,pre+N,-1);
    dist[s]=0;
    pathc[s]=1;
    max_vw[s]=vw[s];
    pq.push(s);     //优先队列初始化
    while(!pq.empty()){     //优先队列非空
        int u=pq.top();     //找到最小u点
        pq.pop();
        if(vis[u]) continue;//找到最小u点
        vis[u]=1;   //找到最近点,加入S集
        for(int i=head[u];~i;i=mp[i].next){     //链式前向星遍历
            int to=mp[i].to;    //链式前向星: u 的后继点 to
            int w=mp[i].w;      //链式前向星: u -> to 边权
            if(!vis[to]){   //松弛
                if(dist[to] > dist[u]+w) { //s->to > s->u->to
                    dist[to] = dist[u] + w;
                    pre[to]=u;
                    pathc[to] = pathc[u];
                    max_vw[to]=max_vw[u]+vw[to];
                    pq.push(to);    //优先队列入队
                }else if(dist[to]==dist[u]+w){
                    pathc[to] += pathc[u];
                    if(max_vw[u]+vw[to] > max_vw[to]){
                        pre[to]=u;
                        dist[to] = dist[u] + w;
                        max_vw[to]=max_vw[u]+vw[to];
                        pq.push(to);    //优先队列入队
                    }
                }
            }
        }
    }
    printf("%d %d\n",pathc[e],max_vw[e]);
}

int main(){
    init_mp();  //初始化链式前向星
    freopen("../in","r",stdin);
    int c1,c2;
    scanf("%d%d%d%d",&N,&M,&c1,&c2);
    FF(i,N){
        int t;
        scanf("%d",&t);
        vw[i]=t;
    }
    FF(i,M){
        int a,b,w;
        scanf("%d%d%d",&a,&b,&w);
        add(a,b,w);
        add(b,a,w);
        g[a][b]=g[b][a]=w;
    }
    dijkstra(c1,c2);
}