首页 > 其他分享 >图论

图论

时间:2023-04-06 22:34:52浏览次数:41  
标签:图论 ver int dijkstra 村庄 heap dist

1. 最短距离

来源Indeed笔试题
原题链接

题目描述

有 \(N\) 个村庄,编号 \(1\) 到 \(N\)。

村庄之间有 \(M\) 条无向道路,第 \(i\) 条道路连接村庄 \(a_i\) 和村庄 \(b_i\),长度是 \(c_i\)。

所有村庄都是连通的。

共有 \(K\) 个村庄有商店,第 \(j\) 个有商店的村庄编号是 \(x_j\)。

然后给出 \(Q\) 个询问,第 \(k\) 个询问给出一个村庄的编号 \(y_k\),问该村庄距离最近的商店有多远?

输入格式

第一行包含两个整数 \(N\),\(M\)。

接下来 \(M\) 行,每行包含三个整数 \(a_i\),\(b_i\),\(c_i\),表示第 \(i\) 条道路连接村庄 \(a_i\) 和村庄 \(b_i\),长度是 \(c_i\)。

再一行包含整数 \(K\)。

接下来 \(K\) 行,每行包含一个整数 \(x_j\),表示第 \(j\) 个有商店的村庄编号是 \(x_j\)。

再一行包含整数 \(Q\)。

接下来 \(Q\) 行,每行包含一个整数 \(y_k\),表示询问编号为 \(y_k\) 的村庄与其距离最近的商店之间的距离。

输出格式

对于每个询问,输出该询问的结果。

数据范围

\(2≤N≤105\),
\(N−1≤M≤min(\frac{N(N−1)}{2},105)\),
\(1≤Q≤105\),
\(1≤K≤N\),
\(1≤c_i≤10000\)

输入样例

7 7
1 2 5
1 4 3
2 3 2
2 5 1
3 6 7
5 6 8
6 7 6
3
7
5
4
7
1
2
3
4
5
6
7

输出样例

3
1
3
0
0
6
0

算法:(堆优化的\(dijkstra\)) \(O(mlogn)\)

算法内容

  • 题意分析:每一个带有商店的村庄都是一个起点(不妨设分别为\(s_1\), \(s_2\), \(s_3\),···, \(s_k\)),所以共有\(k\)个起点,还有有一张包含所有村庄的图;共有\(q\)个查询,在每一次查询中会从这张图中给我们提供一个终点,我们需要输出从起点到终点的最短路径。

  • 我们可以采取\(dp\)的分析思路,按照起点将所有路径分为\(k\)类,求出每一类的最小值取\(min\)即为所有路径的最小值。那么我们如何实现呢?我们可以在所有的\(k\)个起点前面加上一个虚拟的源点,这样就转化为到从源点到不同的终点的最短路问题。

image

  • 由于\(n\)和\(m\)都是\(10^5\),为稀疏图,朴素版的\(dijkstra\)时间复杂度为\(O(n^2)\),会超时,所以应该用堆优化的\(dijkstra\)

C++代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>

#define x first
#define y second

using namespace std;

typedef pair<int, int> PII; //距离,编号

const int N = 1e5 + 10, M = 3 * N;

int n, m, k, q;
int h[N], e[M], w[M], ne[M], idx;
int dist[N];
bool st[N];

void add(int a, int b, int c)
{
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}

void dijkstra()
{
    priority_queue<PII, vector<PII>, greater<PII>> heap;
    memset(dist, 0x3f, sizeof dist);
    
    heap.push({0, 0});
    dist[0] = 0;
    
    while (heap.size())
    {
        auto t = heap.top();
        heap.pop();
        
        int ver = t.y;
        
        if (st[ver]) continue;
        st[ver] = true;
        
        for (int i = h[ver]; i != -1; i = ne[i])
        {
            int j = e[i];
            if (dist[j] > dist[ver] + w[i])
            {
                dist[j] = dist[ver] + w[i];
                heap.push({dist[j], j});
            }
        }
    }
}

int main()
{
    cin >> n >> m;
    
    memset(h, -1, sizeof h);
    
    while (m -- )
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c);
        add(b, a, c);
    }
    
    cin >> k;
    while (k -- )
    {
        int x;
        scanf("%d", &x);
        add(0, x, 0); //加一个虚拟源点
    }
    
    dijkstra();
    
    cin >> q;
    while (q -- )
    {
        int x;
        scanf("%d", &x);
        printf("%d\n", dist[x]);
    }
    
    return 0;
}

标签:图论,ver,int,dijkstra,村庄,heap,dist
From: https://www.cnblogs.com/lhycoder/p/17294461.html

相关文章

  • 【算法学习】图论模板
    注意!并查集只适用于无向图。DFS特点:当前层可以获得下层状态、向下层不断遍历处理方式:递归模板://dfs注意剪枝voiddfs(intu){if(u>n){输出路径return;}for(inti=0;i<n;i++)//遍历点{if(条件)......
  • 2023-04-01 图论问题建模和floodfill
    图论问题建模和floodfillfloodfill(洪泛)实际就是图的遍历1图论问题例子:判断二分图题目来源:LeetCode785is-graph-bipartite:,判断二分图,因为题目中已经给出了邻接表,相当于已经给出了Graph,所以直接用二分图的核心算法即可,参考DFS实现二分图检测实现代码2图的建模和二......
  • 经典图论遍历问题:传递信息
    小朋友A在和ta的小伙伴们玩传信息游戏,游戏规则如下:有n名玩家,所有玩家编号分别为0~n-1,其中小朋友A的编号为0每个玩家都有固定的若干个可传信息的其他玩家(也可能没有)。传信息的关系是单向的(比如A可以向B传信息,但B不能向A传信息)。每轮信息必须需要传递给另一......
  • CF(2E) Keshi in Search of AmShZ (图论,最短路,建边权值变形)
      思路: 关键是操作2的性质:随机找->找一个路径最长的点操作1,阻止建边顾名思义, 发现和最短路很想,从n到每一个点的权值嘛改变权值更新方式,边的权值为:va......
  • 图论--网络流最大流问题
    问题表述:给定一幅图(n个结点,m条边),每一条边有一个容量,现在需要将一些物品从结点s(称为源点)运送到结点t(称为汇点),可以从其他结点中转,求最大的运送量。在介绍最大流问题的解决方法......
  • 图论基础模板
    P3388【模板】割点(割顶)#include<stdio.h>#definemin(x,y)((x)<(y)?(x):(y))intn,m;inthead[20003],last[200003],to[200003],ccnt=0;#defineadd......
  • 离散数学——图论
    设\(A,B\)为任意的两个集合,称\[\{\{a,b\}\mida\inA\wedgeb\inB\}\]为\(A\)与\(B\)的无序积,记作\(A\&B\).为方便起见,将无序积中的无序对\(\{a,......
  • 图论算法
    图论算法第一节基本概念一、什么是图?很简单,点用边连起来就叫做图,严格意义上讲,图是一种数据结构,定义为:graph=(V,E)。V是一个非空有限集合,代表顶点(结点),E代表边的集合。......
  • 图论:Kruskal重构树
    瓶颈路两点间所有路径中\(\max(w)\)最小或\(\min(w)\)最大的路径称为最小/最大瓶颈路。Kruskal重构树考虑kruskal算法的贪心过程,注意到一张图的一个最小生成树是......
  • 搜索与图论3.2
    一、简述本节主要介绍一下有关最小生成树的两个算法,即\(Prim\)算法和\(Kruskal\)算法,适用于无向图。二、Prim算法基本思想\(Prim\)算法有一个适用于稠密图的朴素......