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);
}