今天写单源最短路径算法
也是直接放一题例题讲解~~
815. 公交路线
题目叙述:
给一个数组,表示公车行经的路径
ex.[[1,2,7],[3,6,7]]
表示第0辆公车路径为1->2->7,第1辆公车路径为3->6->7
给定一个起点,一个终点
ex.source = 1, target = 6
最後返回需要搭乘公车的最少数量
假设图无负权重
思路:基於贪心思想,从起点找一个离起点最近的节点->这一个边无法再松弛
->用这一个边去对其他边松弛
从初始节点开始向外一层一层的扩展,将路径逐渐松弛
先用一个Kdis数组纪录每个点与初始点k的距离(k到这些点)
选择Kdis中,最小的那一个节点idx(说明这个节点已经比其他节点到初始点的距离都相对小)来进行扩展
则可得
if(Kdis[idx]+adj[idx][j]<Kdis[j])
Kdis[idx]+adj[idx][j] = Kdis[j]
((一步步向外扩张))
含有将边松弛的概念,也一层层向外扩张能到达的区域
选择Kdis中最小的节点(也就是离初始点最近的节点)来操作就是贪心的思路,已经没有其他节点相对该节点离初始点近,就先拿该节点对其他边进行松弛(可以想成其他边都直接连到初始点),要经过一些节点让路径更好,也就是松弛
class Solution {
public:
int numBusesToDestination(vector<vector<int>>& routes, int source, int target) {
if(source == target) {
return 0;
}
int n = routes.size();
vector<vector<int>> dis(n, vector<int>(n, 1e7));
unordered_map<int, vector<int>> stop2rt;
// for(int i=0; i<n; i++) {
// dis[i][i] = 0;
// }
for(int i=0; i<n; ++i) {
for (int stop : routes[i]) {
for(auto j:stop2rt[stop]){
dis[i][j] = 1;
dis[j][i] = 1;
}
stop2rt[stop].push_back(i);
}
}
int res = 1e7;
for(auto rt:stop2rt[source]){//要遍历所有souce所在的路线
vector<int> dis_start2rt(n, 1e7);
vector<int> vis(n, 0);
dis_start2rt[rt] = 0;
//dijkstra
for(int i = 0; i<n; ++i){
int min_idx = -1, mmin = 1e7;
for(int j = 0; j<n; ++j){
if(!vis[j]&&dis_start2rt[j]<mmin){
mmin = dis_start2rt[j];
min_idx = j;
}
}
if(min_idx==-1){
break;
}
vis[min_idx] = 1;
for(int k = 0; k<n; ++k){
if(!vis[k]){
dis_start2rt[k] = min(dis_start2rt[k], mmin+dis[min_idx][k]);
}
}
}
for (auto end : stop2rt[target]) {
res = min(res, dis_start2rt[end]);
}
}
return res==1e7?-1:res+1;
}
};
思路:
以边为单位,每个边都尝试对路径松弛,松弛n-1次後(程序码写n次,但其实n-1次就可松弛完毕)为最佳路径~~
如果有一个边叫做u->v,并以一个数组纪录起始点到节点的距离dis_start2rt,那可以做这种访问:
if(dis_start2rt[v]>dis_start2rt[u]+dis[u][v]){
dis_start2rt[v] = dis_start2rt[u]+dis[u][v];
}
这种演算法还可以处理负权重,方法是如果n-1次松弛後,如果还有边可以松弛,说明有负权重~~
class Solution {
public:
int numBusesToDestination(vector<vector<int>>& routes, int source, int target) {
if(source == target) {
return 0;
}
int n = routes.size();
vector<vector<int>> dis(n, vector<int>(n, 1e7));
unordered_map<int, vector<int>> stop2rt;
vector<vector<int>> edges(n);
for(int i=0; i<n; ++i) {
for (int stop : routes[i]) {
for(auto j:stop2rt[stop]){
dis[i][j] = 1;
dis[j][i] = 1;
edges[i].push_back(j);
edges[j].push_back(i);
}
stop2rt[stop].push_back(i);
}
}
int res = 1e7;
for(auto rt:stop2rt[source]){//要遍历所有souce所在的路线
vector<int> dis_start2rt(n, 1e7);
vector<int> vis(n, 0);
dis_start2rt[rt] = 0;
queue<int> q;
q.push(rt);
vis[rt] = 1;
while(!q.empty()){
int u = q.front();
q.pop();
vis[u] = false;
for(int k = 0; k<edges[u].size(); ++k){
int v = edges[u][k];
if(dis_start2rt[u]+1<dis_start2rt[v]){
dis_start2rt[v] = dis_start2rt[u]+1;
if(!vis[v]){
q.push(v);
vis[v] = true;
}
}
}
}
for (auto end : stop2rt[target]) {
res = min(res, dis_start2rt[end]);
}
}
return res==1e7?-1:res+1;
}
};
743. 网络延迟时间用这两天讲的方法做一次
#define vt vector
#define pb push_back
#define iipair pair<int, int>
#define cipair pair<char, int>
#define icpair pair<int, char>
#define ispair pair<int, string>
#define sipair pair<string, int>
#define MOD 1e9+7
#define iMat vector<vector<int>>
#define cMat vector<vector<char>>
#define ll long long
#define mp make_pair
class Solution {
public:
int networkDelayTime(vector<vector<int>>& times, int N, int K) {
return bellman(times, N, K);
}
int floyd(vector<vector<int>>& times, int N, int K){
iMat dis(N+1, vt<int>(N+1, 1e7));
for(auto edge:times){
dis[edge[0]][edge[1]] = edge[2];
}
for(int i = 0; i<N+1; ++i){dis[i][i] = 0;}
for(int k = 1; k<N+1; ++k){
for(int i = 1; i<N+1; ++i){
for(int j = 1; j<N+1; ++j){
dis[i][j] = min(dis[i][j], dis[i][k]+dis[k][j]);
}
}
}
int res = 0;
for(int i = 1; i<N+1; ++i){
res = max(res, dis[K][i]);
}
return res==1e7?-1:res;
}
int dijkstra(vector<vector<int>>& times, int N, int K){
iMat dis(N+1, vt<int>(N+3, 1e7));
vt<int> vis(N+1, 0);
vt<int> K2node(N+1, 1e7);
K2node[K] = 0;
for(auto edge:times){
dis[edge[0]][edge[1]] = edge[2];
}
for(int i = 0; i<N; ++i){//进行n次松弛(但其实n-1次就够)
//先找到距离起点最短,未被访问的节点 -->[K->mmin_idx]
int mmin_idx = -1;
int mmin_dis = 1e7;
for(int j = 1; j<N+1; ++j){
if(K2node[j]<mmin_dis&&!vis[j]){
mmin_dis = K2node[j];
mmin_idx = j;
}
}
if(mmin_idx==-1){
break;
}
vis[mmin_idx] = 1;
//利用这条边对路径松弛
for(int j = 1; j<N+1; ++j){
K2node[j] = min(K2node[j], mmin_dis+dis[mmin_idx][j]);
}
}
int res = 0;
for(int i = 1; i<N+1; ++i){
res = max(res, K2node[i]);
}
return res==1e7?-1:res;
}
int bellman(vector<vector<int>>& times, int N, int K){
iMat dis(N+1, vt<int>(N+3, 1e7));
vt<int> K2node(N+1, 1e7);
K2node[K] = 0;
for(auto edge:times){
dis[edge[0]][edge[1]] = edge[2];
}
for(int i = 0; i<N; ++i){ //松弛N次(其实N-1次就够)
//以边为单位
for(auto edge:times){
int u = edge[0];
int v = edge[1];
K2node[v] = min(K2node[v], K2node[u]+edge[2]);
}
}
int res = 0;
for(int i = 1; i<N+1; ++i){
res = max(res, K2node[i]);
}
return res==1e7?-1:res;
}
};
<<: < 关於 React: 开始打地基| 表单内的显示元素,map() ShowAdd 与Key >
In the beginning, the only klingeltöne available w...
CISA书最後一章为资讯资产安全控制及安全事件管理,与CISSP内容大致重叠,差别在需以稽核角度查看...
前言 昨天有说到在储存使用者的密码时,不管是用 AES 把他们加密起来,或是经过 SHA1 杂凑之後...
前言 参考文件: https://kubernetes.io/docs/tasks/access-a...
在前一天,我们提到了价量是有一定的关系在。 正向成长,一般是价量齐涨,若价涨,但量没涨太多。 这时一...