• Dijkstra算法


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

    举例说明:

    图例来自《算法导论》

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

    朴素:

    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;
    }
    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 ;
    }
    
    

    堆优化:

    #include<bits/stdc++.h>
    #define MAXN 100010
    #define MAXM 500010
    #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的思想,但最后所求答案的计算公式并是不“三角不等式”。
  • 相关阅读:
    浅谈MIPS地址对齐问题
    一些使用的linux库
    linux curl网络库的使用方法
    一些json在js和c++ jsoncpp的操作
    Java开发小技巧(六):使用Apache POI读取Excel
    Java开发小技巧(五):HttpClient工具类
    vue-router 组件复用问题
    Vuejs之开发环境搭建
    Java开发小技巧(四):配置文件敏感信息处理
    Java开发小技巧(三):Maven多工程依赖项目
  • 原文地址:https://www.cnblogs.com/cyl-oi-miracle/p/13388308.html
Copyright © 2020-2023  润新知