首页 > 代码库 > L2-001. 紧急救援

L2-001. 紧急救援





#include <cstdio> #include <algorithm> using namespace std; int const MAX = 505; int const INF = 0x3fffffff; int mp[MAX][MAX], val[MAX], path[MAX], dis[MAX], re[MAX], totval[MAX], pathnum[MAX]; mp地图 bool vis[MAX]; int n, m, s, d; void Dijkstra(int v0) //v0出发地的城市编号 { for(int i = 0; i < n; i++) dis[i] = INF; //距离数组初始化为一个极大值 vis[v0] = true; //访问过的v0机位true dis[v0] = 0; //自己到自己的距离为0 totval[v0] = val[v0]; pathnum[v0] = 1; //路得条数 for(int i = 0; i < n; i++) //初始化工作,距离数组中初始化与v0临接的点, path数组中初始化临接点的前驱节点,到达临接点救援队的数量,到达临接点路径的条数 { if(mp[v0][i] != INF && i != v0) { dis[i] = mp[v0][i]; //v0到i得距离 path[i] = v0; //到达i得前一个为v0 totval[i] = val[v0] + val[i]; // pathnum[i] = 1; } } for(int i = 0; i < n - 1; i++) //这里是n-1的原因:v0已经处理过了,只需要n-1次,所有的节点就会都被拿出来。 { int mi = INF, mival = 0, u = v0; for(int j = 0; j < n; j++) { if(!vis[j] && dis[j] < mi) //从临接点中找出一个与u距离最近的,拿到代号为u。 { mi = dis[j]; u = j; } } vis[u] = true; //访问u for(int j = 0; j < n; j++) { if(!vis[j]) { if(dis[u] + mp[u][j] < dis[j]) //对u的每一个相邻的点,使用u到原点的距离加上u到j的距离,如果小于j到原点的距离,则更新。如果j与u没有边联通,则mp[u][j]无穷大,不可能更新 { pathnum[j] = pathnum[u]; //更新路的条数 dis[j] = dis[u] + mp[u][j]; //更新距离 totval[j] = totval[u] + val[j]; // 更新救援队的数目 path[j] = u; //设定前驱节点 } else if(dis[u] + mp[u][j] == dis[j]) { pathnum[j] += pathnum[u]; //通过u到达j的距离,与不通过u相同,则用以前的路数加上u的路数 if(totval[j] < totval[u] + val[j]) //距离相等,更新救援队的数目 { totval[j] = totval[u] + val[j]; path[j] = u; //在距离基础上比较救援队的数量,想在距离相等,那个的救援队数量大,就使用哪个作为前驱节点 } } } } } } int main() { scanf("%d %d %d %d", &n, &m, &s, &d); for(int i = 0; i < n; i++) scanf("%d", &val[i]); //存储城市救援队的数量 for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) mp[i][j] = INF; //距离的初始化 int x, y, l; for(int i = 0; i < m; i++) { scanf("%d %d %d", &x, &y, &l); mp[x][y] = min(mp[x][y], l); //为什么是较小的,mp是全局变量,最初被初始化为INF,地图,快速通道的长度 mp[y][x] = mp[x][y]; } Dijkstra(s); //拿到需要的数据了,如路径,条数 int num = 0, cur = d; while(cur != s) //将path中逆序的路径顺序放到re数组中去。 { re[num ++] = cur; cur = path[cur]; } re[num ++] = s; //起点放进顺序路径中 printf("%d %d\n", pathnum[d], totval[d]); //输出路的条数,支援队伍的数量 for(int i = num - 1; i > 0; i--) printf("%d ", re[i]); printf("%d\n", re[0]); }

dijkstra算法比较复杂,看了好一阵才算完全弄明白,如果不了解算法就来看代码,真的很蛋疼,应该先完全了解dijkstra算法,然后知道这类问题的不同情况,以下列出,然后根据套路来看代码,就会容易很多

求最短路径的条数

counts[s] = 1;

如果找到更短路: count[w] = count[v];

如果找到等长路:count[w] = count[v] + count[w]

 

 

要求边数最少的最短路:

counts[0];

如果找到更短路:count[w] = count[v] + 1

如果找到等长路: count[w]  = count[v] + 1    //这是抄的mooc上变得,个人觉得这里应该是

if(count[v]+1<count[w])

  count[w] = count[v]+1

L2-001. 紧急救援