Dijkstra

Dijkstra

Dijkstra 算法是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题

特点:是从起点开始,采用贪心算法的策略,每次遍历到始点距离最近未访问过的顶点的邻接节点,直到扩展到终点为止。

举例说明:

Dijkstra 算法在运行的过程中维持的关键信息是一组节点的集合 S S S

从源节点 s s s 到该集合中每个节点之间的最短路径已经被找到。

算法重复从节点集 V − S V-S VS 中选择最短路径估计最小的节点 u u u ,将 u u u 加入到集合 S S S ,然后对所有从 u u u 出发的边来进行松弛。

(我们可以用一个最小优先队列 Q = V − S Q=V-S Q=VS

上图的解释

源结点s为左边的结点。每个结点中的数值为该结点的最短路径的估计值,加了阴影的边表示前驱值。

黑色的结点属于S集合,白色的结点属于Q。

注意:要求图中不存在负权边。

朴素:

void INIT()
{
	memset(vis,0,sizeof(vis));	memset(d,0,sizeof(d));	memset(p,0,sizeof(p));
	vis[sta]=1;
	for(int i=1;i<=n;++i)		d[i]=a[sta][i];
	for(int i=1;i<=n;++i)		p[i]=sta;
	d[sta]=0;	p[sta]=0;
    //sta(start)起点
}
void Dijkstra()
{
	int k;	init();
	for(int i=1;i<=n-2;++i)
	{
		m=max1;
		for(int j=1;j<=n;++j)
		{
			if(d[j]<m && !vis[j])
			{m=d[j];	k=j;}
		}
		if(m==max1)		break;
		vis[k]=1;
		for(int j=1;j<=n;++j)
			if(d[k]+a[k][j]<d[j])
			{
				d[j]=d[k]+a[k][j];
				p[j]=k;	
			}
	}
	printf("%d",d[end]);
	return ;
}

堆优化:

#define INF 0x3f3f3f3f
struct EDGE{int to,dis,next;}	e[MAXM];
struct node
{
    int dis,pos;
    bool operator <( const node &x ) const	{return x.dis < dis;}
    //重定向 
};
std::priority_queue< node > q;
int n,m,s;
int adj[MAXN],dis[MAXN],cnt;
bool vis[MAXN];
void addedge(int u,int v,int d)	//链式前向星 
{
    ++cnt;e[cnt].dis=d;e[cnt].to=v;e[cnt].next=adj[u];adj[u]=cnt;
}
void Dijkstra()
{
    dis[s]=0;	q.push(( node ){0,s});	//先将源点入队列 
    while(!q.empty())
    {
        node temp=q.top();	q.pop();
        int x=temp.pos;
        	if(vis[x])	continue;		//对未访问节点进行扫描 
        vis[x]=1;
        for(int i=adj[x];i;i=e[i].next)
        {
            int y=e[i].to;
            if(dis[y]>dis[x]+e[i].dis)		//三角不等式,松弛
            {
                dis[y]=dis[x]+e[i].dis;
                if(!vis[y])
                    q.push( (node){dis[y], y} );	//邻接节点入队列 
            }
        }
    }
}
int main()
{
    scanf("%d%d%d",&n,&m,&s);
    for(int i=1;i<=n;++i) dis[i]=INF;		//初始化 
    for(int i=0;i<m;++i)
    {
        int u,v,d;	scanf("%d%d%d",&u,&v,&d);
        addedge(u,v,d);
    }
    Dijkstra();
    for(int i=1;i<=n;++i)	printf("%d ",dis[i]);
    return 0;
}

做题感悟:

  • 有的题目是在问题中套着最短路的模型,要分析出题目中所求的“路径”,然后使用Dijkstra算法。
  • 在“三角不等式”的部分注意,有些题目是运用Dijkstra的思想,但最后所求答案的计算公式并是不“三角不等式”。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值