图论算法----最短路

经典算法

单源最短路:

1.Bellman_ford(可判负环,可有负边)

d[i]表示起点S到i的最短路,那么d[i]=min{d[j]+w[j][i]}且存在j->i的边代价为w[j][i]

经过证明如果不存在负圈最多通过V-1次松弛就可以完成复杂度O(V*E)(V为结点数,E为边数)

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <set>
 5 #include <algorithm>
 6 #include <map>
 7 #include <queue>
 8 #include<vector>
 9 #define maxn 50010
10 #define maxm 100010
11 #define INF 0x3fffffff
12 using namespace std;
13 struct edge{
14     int from,to,w;
15     edge(){}
16     edge(int _u,int _v,int _w){
17         from=_u,to=_v,w=_w;
18     }
19 };
20 edge G[maxm];
21 int V,E;
22 void addedge(int u,int v,int w){
23     G[E++]=edge(u,v,w);
24 }
25 int d[maxn];
26 int n,m;
27 //d[i] = min{d[j]+w[j][i]} {j->i}
28 void bellman_ford(int s){
29     V=n;
30     for(int i=0;i<V;++i)d[i]=INF;
31     d[s]=0;
32     while(1){
33         bool flag =false;
34         for(int i=0;i<E;++i){
35             edge e = G[i];
36             if(d[e.from]!=INF&&d[e.to]>d[e.from]+e.w){
37                 d[e.to] = d[e.from]+e.w;
38                 flag = true;
39             }
40         }
41         if(!flag)break;
42     }
43 }
44 int main (){
45     while(scanf("%d%d",&n,&m)!=EOF){
46         if(n==0&&m==0)break;
47         int u,v,w;
48         E=0;
49         for(int i=0;i<m;++i){
50             scanf("%d%d%d",&u,&v,&w);
51             addedge(u-1,v-1,w);
52             addedge(v-1,u-1,w);
53         }
54         bellman_ford(0);
55         printf("%d\n",d[n-1]);
56     }
57 }
View Code

判负环:看一下是不是多于V-1次松弛,如果有则存在负环

 1 bool HaveNagativeLoop(){
 2     memset(d,0,sizeof(d));
 3     for(int i=0;i<V;++i){
 4         for(int j=0;j<E;++j){
 5             edge e = G[j];
 6             if(d[e.to]>d[e.from]+e.w){
 7                 d[e.to] = d[e.from]+e.w;
 8                 if(i==V-1)return true;
 9             }
10         }
11     }
12     return false;
13 }
View Code

 2.dijkstra(无负边)

对于上述的d[i]=min{d[j]+w[j][i]}如果d[j]当前值不是d[j]能达到的最小值那么显然在后面d[i]还将更新,如何避免这种情况

选择d[j]已经是最小,即S->j的最短距离不再更新,如何选取?每次选择距离最短且未被使用的结点,用这个结点对其他节点进行松弛复杂度O(V*V)

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <set>
 5 #include <algorithm>
 6 #include <map>
 7 #include <queue>
 8 #include<vector>
 9 #define maxn 1010
10 #define maxm 100010
11 #define INF 0x3fffffff
12 using namespace std;
13 //d[i]=min{d[j]+w[j][i]} {d[j]已经不再更新}
14 //每次找最小d[j]然后松弛
15 int G[maxn][maxn];
16 int d[maxn];
17 bool used[maxn];
18 int V;
19 void dijksta(int s){
20     for(int i=0;i<V;++i){
21         used[i]=false;
22         d[i]=INF;
23     }
24     d[s]=0;
25     while(1){
26         int v =-1;
27         for(int i=0;i<V;++i){
28             if(!used[i]&&(v==-1||d[i]<d[v]))v=i;
29         }
30         if(v==-1)break;
31         used[v]=true;
32         for(int i=0;i<V;++i){
33             d[i]=min(d[i],d[v]+G[v][i]);
34         }
35     }
36 }
37 void init(int n){
38     V = n;
39     for(int i=0;i<V;++i){
40         for(int j=0;j<V;++j){
41             if(i==j)G[i][j]=0;
42             else G[i][j]=INF;
43         }
44     }
45 }
46 int main (){
47     int n,m;
48     while(scanf("%d%d",&n,&m)!=EOF){
49         if(n==0&&m==0)break;
50         int u,v,w;
51         init(n);
52         for(int i=0;i<m;++i){
53             scanf("%d%d%d",&u,&v,&w);
54             G[u-1][v-1]=w;
55             G[v-1][u-1]=w;
56         }
57         dijksta(0);
58         printf("%d\n",d[n-1]);
59     }
60 }
View Code

 来优化一下上面的算法,每次需要选择最短的一个结点,这个可以使用一个优先队列来维护当前所有边里面权值最小的边,所以算法复杂度变为O(V*log(E))

使用邻接表存储图比较容易写

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <set>
 5 #include <algorithm>
 6 #include <map>
 7 #include <queue>
 8 #include<vector>
 9 #define maxn 1010
10 #define maxm 100010
11 #define INF 0x3fffffff
12 using namespace std;
13 struct edge {
14     int to,w;
15     edge(){}
16     edge(int _to,int _w){
17         to=_to;w=_w;
18     }
19 };
20 typedef pair<int,int> P;
21 int V;
22 vector<edge> G[maxn];
23 int d[maxn];
24 void dijkstra(int s){
25     priority_queue<P,vector<P>,greater<P> >q;
26     for(int i=0;i<V;++i)d[i]=INF;
27     d[s]=0;
28     q.push(P(d[s],s));
29     while(!q.empty()){
30         P p = q.top();
31         q.pop();
32         int v = p.second;
33         if(d[v]<p.first)continue;
34         for(int i=0;i<G[v].size();++i){
35             edge e = G[v][i];
36             if(d[e.to]>d[v]+e.w){
37                 d[e.to]=d[v]+e.w;
38                 q.push(P(d[e.to],e.to));
39             }
40         }
41     }
42 }
43 int main (){
44     int n,m;
45     while(scanf("%d%d",&n,&m)!=EOF){
46         for(int i=0;i<n;++i)G[i].clear();
47         V=n;
48         if(n==0&&m==0)break;
49         int u,v,w;
50         for(int i=0;i<m;++i){
51             scanf("%d%d%d",&u,&v,&w);
52             G[u-1].push_back(edge(v-1,w));
53             G[v-1].push_back(edge(u-1,w));
54         }
55         dijkstra(0);
56         printf("%d\n",d[n-1]);
57     }
58 }
View Code

 3.floyd(任意两点的最短路,可有负边)

dp的思想   d[k+1][i][j]表示从0~k 里面选择中间结点从i到j的最短距离 那么当k为-1时d[0][i][j]=w[i][j] 

考虑如何转移 从0~k-1中间选到0~k中选新的方案有两种情况:

不经过第k个结点 那么 d[k+1][i][j]=d[k][i][j]

经过第k个结点   那么d[k+1][i][j] = d[k][i][k]+d[k][k][j]

则方程为d[k+1][i][j]=min{ d[k][i][j],d[k][i][k]+d[k][k][j]}

可以使用滚动数组来优化空间,由于d[k+1][][]只与d[k][][]有关,所以只要保证k是从小到大枚举的就可以节省以为空间,复杂度为O(V*V*V)

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <set>
 5 #include <algorithm>
 6 #include <map>
 7 #include <queue>
 8 #include<vector>
 9 #define maxn 1010
10 #define maxm 100010
11 #define INF 0x3fffffff
12 using namespace std;
13 int d[maxn][maxn];
14 int V;
15 void init(int n){
16     V=n;
17     for(int i=0;i<V;++i){
18         for(int j=0;j<V;++j){
19             if(i==j)d[i][j]=0;
20             else d[i][j]=INF;
21         }
22     }
23 }
24 void floyd(){
25     for(int k=0;k<V;++k){
26         for(int i=0;i<V;++i){
27             for(int j=0;j<V;++j){
28                 d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
29             }
30         }
31     }
32 }
33 int main (){
34     int n,m;
35     while(scanf("%d%d",&n,&m)!=EOF){
36         if(n==0&&m==0)break;
37         int u,v,w;
38         init(n);
39         for(int i=0;i<m;++i){
40             scanf("%d%d%d",&u,&v,&w);
41             d[u-1][v-1]=w;
42             d[v-1][u-1]=w;
43         }
44         floyd();
45         printf("%d\n",d[0][n-1]);
46     }
47 }
View Code

 

转载于:https://www.cnblogs.com/shuzy/p/3776575.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1 目标检测的定义 目标检测(Object Detection)的任务是找出图像中所有感兴趣的目标(物体),确定它们的类别和位置,是计算机视觉领域的核心问题之一。由于各类物体有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具有挑战性的问题。 目标检测任务可分为两个关键的子任务,目标定位和目标分类。首先检测图像中目标的位置(目标定位),然后给出每个目标的具体类别(目标分类)。输出结果是一个边界框(称为Bounding-box,一般形式为(x1,y1,x2,y2),表示框的左上角坐标和右下角坐标),一个置信度分数(Confidence Score),表示边界框中是否包含检测对象的概率和各个类别的概率(首先得到类别概率,经过Softmax可得到类别标签)。 1.1 Two stage方法 目前主流的基于深度学习的目标检测算法主要分为两类:Two stage和One stage。Two stage方法将目标检测过程分为两个阶段。第一个阶段是 Region Proposal 生成阶段,主要用于生成潜在的目标候选框(Bounding-box proposals)。这个阶段通常使用卷积神经网络(CNN)从输入图像中提取特征,然后通过一些技巧(如选择性搜索)来生成候选框。第二个阶段是分类和位置精修阶段,将第一个阶段生成的候选框输入到另一个 CNN 中进行分类,并根据分类结果对候选框的位置进行微调。Two stage 方法的优点是准确度较高,缺点是速度相对较慢。 常见Tow stage目标检测算法有:R-CNN系列、SPPNet等。 1.2 One stage方法 One stage方法直接利用模型提取特征值,并利用这些特征值进行目标的分类和定位,不需要生成Region Proposal。这种方法的优点是速度快,因为省略了Region Proposal生成的过程。One stage方法的缺点是准确度相对较低,因为它没有对潜在的目标进行预先筛选。 常见的One stage目标检测算法有:YOLO系列、SSD系列和RetinaNet等。 2 常见名词解释 2.1 NMS(Non-Maximum Suppression) 目标检测模型一般会给出目标的多个预测边界框,对成百上千的预测边界框都进行调整肯定是不可行的,需要对这些结果先进行一个大体的挑选。NMS称为非极大值抑制,作用是从众多预测边界框中挑选出最具代表性的结果,这样可以加快算法效率,其主要流程如下: 设定一个置信度分数阈值,将置信度分数小于阈值的直接过滤掉 将剩下框的置信度分数从大到小排序,选中值最大的框 遍历其余的框,如果和当前框的重叠面积(IOU)大于设定的阈值(一般为0.7),就将框删除(超过设定阈值,认为两个框的里面的物体属于同一个类别) 从未处理的框中继续选一个置信度分数最大的,重复上述过程,直至所有框处理完毕 2.2 IoU(Intersection over Union) 定义了两个边界框的重叠度,当预测边界框和真实边界框差异很小时,或重叠度很大时,表示模型产生的预测边界框很准确。边界框A、B的IOU计算公式为: 2.3 mAP(mean Average Precision) mAP即均值平均精度,是评估目标检测模型效果的最重要指标,这个值介于0到1之间,且越大越好。mAP是AP(Average Precision)的平均值,那么首先需要了解AP的概念。想要了解AP的概念,还要首先了解目标检测中Precision和Recall的概念。 首先我们设置置信度阈值(Confidence Threshold)和IoU阈值(一般设置为0.5,也会衡量0.75以及0.9的mAP值): 当一个预测边界框被认为是True Positive(TP)时,需要同时满足下面三个条件: Confidence Score > Confidence Threshold 预测类别匹配真实值(Ground truth)的类别 预测边界框的IoU大于设定的IoU阈值 不满足条件2或条件3,则认为是False Positive(FP)。当对应同一个真值有多个预测结果时,只有最高置信度分数的预测结果被认为是True Positive,其余被认为是False Positive。 Precision和Recall的概念如下图所示: Precision表示TP与预测边界框数量的比值 Recall表示TP与真实边界框数量的比值 改变不同的置信度阈值,可以获得多组Precision和Recall,Recall放X轴,Precision放Y轴,可以画出一个Precision-Recall曲线,简称P-R
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值