图论基础:最短路与最小生成树

图论基础:最短路与最小生成树

一、邻接矩阵和邻接表

邻接矩阵:二维数组

邻接表:模拟链表

二、单源最短路径:dijkstra

步骤:

  1. dis[i]=+oo,dis[s]=0
  2. 找到未标记的dis最小节点并标记
  3. 扫描它的出边更新其他节点
  4. 重复2,3,用n-1次标记所有节点

代码

void dijkstra()
{
	for (int i=0;i<=n;i++) dis[i]=inf;
    dis[s]=0;
    for (int i=1;i<n;i++)
    {
    	int x=0;
    	for (int j=1;j<=n;j++)
    	{
    		if (used[j]==0&&dis[j]<dis[x]) x=j;
		}
		used[x]=1;
		for (int j=h[x];j;j=nxt[j])
		{
			dis[t[j]]=min(dis[t[j]],dis[x]+v[j]);
		}
	}
}

时间复杂度: O ( n m ) O(nm) O(nm)

三、优先队列优化dij

每次从堆中找最小值

步骤:

  1. dis[i]=+oo,dis[s]=0
  2. 从堆中取出未标记的dis节点并标记(若已标记就扔掉)
  3. 扫描它的出边更新其他节点
  4. 重复2,3,在队列空前标记所有节点

代码

priority_queue<pair<int,int> >q; 
void dijkstra()
{
	for (int i=0;i<=n;i++) dis[i]=inf;
    dis[s]=0;
    q.push(make_pair(0,s));
    while (q.size())
    {
    	int x=q.top().second;
    	q.pop();
    	if (used[x]) continue;
    	used[x]=1;
    	for (int j=h[x];j;j=nxt[j])
    	{
    		if (dis[t[j]]>dis[x]+v[j])
    		{
    			dis[t[j]]=dis[x]+v[j];
    			q.push(make_pair(-dis[t[j]],t[j]));
			}
		}
	}
}

时间复杂度 O ( m log ⁡ n ) O(m\log n) O(mlogn)

四、spfa

如果队列不为空:

  1. 取出第一个点
  2. 沿它寻找更优的点:更新,放入队列中
void spfa()
{
    for (int i=1;i<=n;i++) dis[i]=inf;
    int u,w;
    q.push(s);
    dis[s]=0;
    vis[s]=1;
    while (!q.empty())
    {
        u=q.front();
        q.pop();
        vis[u]=0;
        for (int i=h[u];i!=0;i=nxt[i])
        {
            w=t[i];
            if (dis[w]>dis[u]+v[i])
            {
                dis[w]=dis[u]+v[i];
                if (!vis[w])
                {
                    vis[w]=1;
                    q.push(w);
                }
            }
        }
    }
}

时间复杂度 O ( V E ) O(VE) O(VE)

优点是可以解决负数的边(上面两个不行)。缺点容易退化成 O ( n m ) O(nm) O(nm)

五、floyd

多源最短路。用 d [ k ] [ i ] [ j ] d[k][i][j] d[k][i][j]表示经过编号不超过超过 k k k的点,从 i i i j j j的最短路。 f [ k ] [ i ] [ j ] = m i n ( f [ k − 1 , i , j ] , m i n [ k − 1 , i , k ] + m i n [ k − 1 , k , j ] ) f[k][i][j]=min(f[k-1,i,j],min[k-1,i,k]+min[k-1,k,j]) f[k][i][j]=min(f[k1,i,j],min[k1,i,k]+min[k1,k,j])。把第一维舍去即可。

缺点:时空消耗大,不能处理负环。

五、最短路的各种拓展

  1. 分层图最短路
  2. 传递闭包(Floyd)
  3. 最小环(Floyd无向图,堆优dij有向图)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值