今天也是为了cc,努力奋斗的一天ヾ(≧▽≦*)o
疑问
暂无
代码——Dijkstra版
#include<stdio.h>
#include<algorithm>
using namespace std;
//最大的点的数量
const int MAXV = 1010;
//定义不可达时的距离
const int INF = 1000000000;
//输入节点数
int n;
//源点s
int s;
//终点t
int t;
//无向图G
int G[MAXV][MAXV];
//标记是否访问数组
bool vis[MAXV] = {false};
//单源最短路径数组
int d[MAXV];
//单源最短路径条数数组
int num[MAXV] = {0};
//救援数rescue数组
int r[MAXV]={0};
//单源最短路径最大救援数数组
int maxr[MAXV]={0};
//单源最短路径Dijkstra算法
void Dijkstra(){
//1.初始化操作
//首先,数组d[MAXV]中的单源最短路径设置为INF
fill(d,d+MAXV,INF);
//将起点s到自己的距离设置为0
d[s] = 0;
//将起点s的路径数设置为1
num[s] = 1;
//将起点s的单源最短路径最大救援数设置为它的初始值
maxr[s] = r[s];
for(int i=0;i<n;i++){
//2.求最近的点
int u = -1;
int MIN = INF;
for(int j=0;j<n;j++){
if(vis[j] == false && d[j] != INF && d[j] < MIN){
u = j;
MIN = d[j];
}
}
//设置最近的点已经被访问
vis[u] = true;
//如果u还是-1,说明存在不相连的点,则退出循环
if(u == -1){
return;
}
//3.对d[v]进行更新
for(int v=0;v<n;v++){
if(vis[v] == false && G[u][v] != INF){
if(G[u][v] + d[u] < d[v]){
d[v] = G[u][v] + d[u];
num[v] = num[u];
maxr[v] = r[v] + maxr[u];
}else if(G[u][v] + d[u] == d[v]){
num[v] += num[u];
if(maxr[v] < r[v] + maxr[u]){
maxr[v] = r[v] + maxr[u];
}
}
}
}
}
printf("%d %d",num[t],maxr[t]);
}
int main(){
//numberOfRoads
int nor;
scanf("%d %d %d %d",&n,&nor,&s,&t);
//初始化图G
fill(G[0],G[0]+MAXV*MAXV,INF);
for(int i=0;i<n;i++){
scanf("%d",&r[i]);
}
for(int i=0;i<nor;i++){
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
G[a][b] = c;
G[b][a] = c;
}
Dijkstra();
return 0;
}
代码——Bellman-Ford版
#include<stdio.h>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;
const int MAXV = 510;
const int INF = 1000000000;
struct Node{
int v;
int dis;
};
//顶点的数量
int n;
//边的数量
int m;
//起点
int s;
//终点
int t;
//邻接表
vector<Node> Adj[MAXV];
//存放最短路径的数组
int d[MAXV];
//存放每个点的权重的数组
int weight[MAXV];
//存放最大权重的数组
int w[MAXV];
//存放前驱节点
set<int> pre[MAXV];
//存放最短路径的个数
int num[MAXV];
bool Bellman(int s){
fill(d,d+MAXV,INF);
fill(w,w+MAXV,0);
fill(num,num+MAXV,0);
d[s] = 0;
w[s] = weight[s];
num[s] = 1;
for(int i=0;i < n-1;i++){
for(int u=0;u < n;u++){
for(int j=0;j<Adj[u].size();j++){
int v= Adj[u][j].v;
int dis = Adj[u][j].dis;
if(d[u] + dis < d[v]){
d[v] = d[u] + dis;
pre[v].clear();
pre[v].insert(u);
num[v] = num[u];
w[v] = w[u] + weight[v];
}else if(d[u] + dis == d[v]){
pre[v].insert(u);
num[v] = 0;
for(set<int>::iterator it = pre[v].begin();it != pre[v].end();it++){
num[v] += num[*(it)];
}
if(w[u] + weight[v] > w[v]){
w[v] = w[u] + weight[v];
}
}
}
}
}
for(int u=0;u<n;u++){
for(int j=0;j<Adj[u].size();j++){
int v = Adj[u][j].v;
int dis = Adj[u][j].dis;
if(d[u] + dis < d[v]){
return false;
}
}
}
printf("%d %d",num[t],w[t]);
return true;
}
int main(){
scanf("%d %d %d %d",&n,&m,&s,&t);
for(int i=0;i<n;i++){
scanf("%d",&weight[i]);
}
for(int i=0;i<m;i++){
int x,y,z;
scanf("%d %d %d",&x,&y,&z);
Node n1;
Node n2;
n1.v = x;
n1.dis = z;
n2.v = y;
n2.dis = z;
Adj[x].push_back(n2);
Adj[y].push_back(n1);
}
Bellman(s);
return 0;
}
反思
- 忘记对邻接矩阵
G[MAXV][MAXV]
进行初始化了,然后。。。发现了也不知道该怎么初始化,2333,《算法笔记》上对二维数组的初始化,我受教了:fill(G[0],G[0]+MAXV*MAXV,INF)
; - 感觉这个Dijkstra其实还好,只要理解了伪代码,自己写起来还是比较容易的;
- 这道题目比较综合,不是“裸”的Dijkstra,加入了点权和最短路径数量,比较综合,值得一做,做一道题,训练三个点,爽呀~~~~
- 集合的遍历,可以使用迭代器进行,我又忘记了,呜呜呜:
for(set<int>::iterator it = pre[v].begin();it != pre[v].end();it++){ num[v] += *(it); }
- 集合
set
使用迭代器遍历时,不能使用it < pre[v].end()
,只能使用it != pre[v].end
; - 集合
set
清空操作为clear()
; - 结构体的构造函数:
struct Node{
int v,dis;
Node(int _v,int _dis) : v(_v),dis(_dis) {}
}