单源最短路径:一个点(源点)到其余各个顶点的最短路劲
#include
#include
#define inf 99999999
int a[1002][1002];
int main()
{
memset(a,inf,sizeof(a));///若题目有重边,则需要先将邻接矩阵初始化为inf,在后面读入边的时候再加if判断
int dis[1002]={},book[1002]={};//book数组初始化
int N,M,x,y,z,t,sum=0;
scanf("%d%d",&N,&M);//读入N和M,N表示顶点个数,M表示边的条数
//初始化邻接矩阵
for(int i=1;i<=N;i++){
for(int j=1;j<=N;j++){
if(i==j) a[i][j]=0;
else a[i][j]=inf;
}
}
//读入边
for(int k=0;k<M;k++){
scanf("%d%d%d",&x,&y,&z);
if(z<a[x][y])//若题目有重边,则需要加这条if语句判断
a[x][y]=z;
}
//初始化dis数组,这里是1号顶点到其余各个顶点的初始路程
for(int q=1;q<=N;q++){
dis[q]=a[1][q];
}
book[1]=1;//标记源点
//Dijkstras算法核心语句
for(int i=1;i<=N-1;i++){
//找到离1号顶点最近的点
int min=inf;
for(int j=1;j<=N;j++){
if(book[j]==0&&dis[j]<min){
min=dis[j];
t=j;
}
}
book[t]=1;
for(int o=1;o<=N;o++){
if(a[t][o]<inf){
if(dis[o]>dis[t]+a[t][o])
dis[o]=dis[t]+a[t][o];
}
}
}
//输出最终结果
for(int k=1;k<=N;k++){
printf("%d ",dis[k]);
//sum+=dis[k];
}
//printf("%d\n",sum);
return 0;
}
// Dijkstra算法
#include
#include
#define INF 20000000000000
int n;
int visit[1001];
long long state[1001];
int G1[1001][1001];
int Min()
{
int place=0,i;
long long min=INF;
for(i=1;i<=n;i++)
if(!visit[i]&&min>state[i])
{
min=state[i];
place=i;
}
return place;
}
long long Dijkstra(int G[][1001])
{
int u,i;
long long sum;
memset(visit,0,sizeof(visit));
state[1]=0;
for(i=2;i<=n;i++)
state[i]=INF;
while(1)
{
u=Min();
if(u==0)break;
visit[u]=1;
for(i=1;i<=n;i++)
{
if(i==u)continue;
if(!visit[i]&&G[u][i]&&state[i]>state[u]+G[u][i])state[i]=state[u]+G[u][i];
}
}
for(i=1,sum=0;i<=n;i++)
sum+=state[i];
return sum;
}
int main()
{
int s,d,w,dage,i;
scanf("%d%d",&n,&dage);
memset(G1,0,sizeof(G1));
for(i=1;i<=dage;i++)
{
scanf("%d%d%d",&s,&d,&w);
if(G1[s][d]==0||G1[s][d]>w) G1[s][d]=w;
}
printf("%lld\n",Dijkstra(G1));
return 0;
}
// SPFA算法
#include
#include
#include
#include
#include
using namespace std;
const int MAX=1005;
const int inf=0x3f3f3f3f;
struct NODE
{
int to,len;
NODE *next;
};
NODE *p[MAX],node[MAX*MAX];
int cou;
void add(int from,int to,int len)
{
node[cou].next=p[from];
node[cou].to=to;
node[cou].len=len;
p[from]=&node[cou++];
}
int SPFA_List(int from,int to,int n)
{
queue<int> q;
int dis[MAX],cnt[MAX],neg=0;
bool inq[MAX];
int i;
for(i=1;i<=n;++i)
dis[i]=inf;
memset(cnt,0,sizeof(cnt));
memset(inq,false,sizeof(inq));
dis[from]=0;
q.push(from);
inq[from]=cnt[from]=1;
while(!q.empty())
{
int now=q.front();
q.pop();
inq[now]=false;
NODE *head=p[now];
while(head!=NULL)
{
int v=head->to;
int len=head->len;
if(dis[v]>dis[now]+len)
{
dis[v]=dis[now]+len;
if(!inq[v])
{
inq[v]=true;
q.push(v);
cnt[v]++;
if(cnt[v]>n)
{
neg=1;
break;
}
}
}
head=head->next;
}
if(neg) break;
}
if(neg)
{
cout<<"spfa_list say: exist negative circle!!!!"<<endl;
return -1;
}
int ans=0;
for(i=2;i<=n;++i)
ans+=dis[i];
return ans;
}
int main()
{
int n,m,i,j,u,v,w;
scanf("%d%d",&n,&m);
cou=0;
for(i=1;i<=n;++i)
p[i]=NULL;
//for(i=1;i<=n;++i)
// for(j=1;j<=n;++j)
// map[i][j]=inf;
for(i=0;i<m;++i)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
//if(w
单源最短路径算法小结
待搜索的图都指有向图(无向图类似)。储存方式均为邻接表
一、广度优先搜索(BFS)
时间复杂度:O(V+E),效率很高
适用范围:(很窄)仅适于无权边的图。即每条边长度都为1的情况
代码复杂程度:一般,需队列
二、Bellman-Ford
时间复杂度:O(VE),效率一般
适用范围:(很广)允许存在负权边,能够判断图中是否存在从源点可到达的负权环路
代码复杂程度:较易
三、有向无环图算法
时间复杂度:O(V+E),效率很高
适用范围:(很窄)仅适于有向无环图
代码复杂程度:一般,需拓扑排序
四、Dijkstra
适用范围:(一般)不允许存在负权边
这个算法复杂度取决于"取最小"(Extract-min)操作使用的算法
Extract-min操作 时间复杂度 代码复杂程度
顺序检测所有点决定最小值 O(V^2) 一般
使用Binary-Heap(优先队列) O((V+E)lgV) 较复杂
使用Fibonacci-Heap O(VlgV+E) 较复杂
五、SPFA (Shortest Path Faster Algorithm)
时间复杂度:O(kE),k为一较小常量。效率很高
适用范围:(较广),允许存在负权边,但不允许负权环路
代码复杂程度:较易,需队列
这个算法可算是 Bellman-Ford 的优化版本,去除冗余的Relax操作,效率有很大提升