首页 > 其他分享 >【蓝桥-大试牛刀7-最短路专场】题解

【蓝桥-大试牛刀7-最短路专场】题解

时间:2024-03-11 10:22:18浏览次数:25  
标签:大试 int 题解 cnt st 蓝桥 vis push true

最短路1

floyd说白了就是个暴力,用三层循环枚举所有路径,然后留下权值最小的一条

大概就长这个样


for(中转点k)
	for(起点i)
		for(终点j)
			d[i][j] = min(d[i][j], d[i][k] + d[k][j]);

注意这个题的数据有重边,输入的时候留下最小的,这样就做完了

int d[N][N];

void solve()
{
    memset(d, 0x3f, sizeof d);

    int n, m;cin >> n >> m;
    for(int i = 1; i <= m; ++ i)
    {
        int u, v, w;cin >> u >> v >> w;
        d[u][v] = min(d[u][v], w);
        d[v][u] = min(d[v][u], w);
    }

    for(int i = 1; i <= n; ++ i)d[i][i] = 0;

    for(int k = 1; k <= n; ++ k)
        for(int i = 1; i <= n; ++ i)
            for(int j = 1; j <= n; ++ j)
                d[i][j] = min(d[i][j], d[i][k] + d[k][j]);

    for(int i = 1; i <= n; ++ i)
    {
        for(int j = 1; j <= n; ++ j)
        {
            if(d[i][j] <= inf)cout << d[i][j] << ' ';
            else cout << -1 << '\n';
        }
        cout << '\n';
    }
}

最短路2

之前发的那个提示第一步操作其实没说全,这次来个全的。

1.re-weight

重新调整每一条边的权值。

建立一个编号为0的点,与所有节点相连,且权值为0,然后用Bellman-Ford求0号节点到所有点的最短路。

如果不存在负环,我们就得到了一个\(h[]\)数组,接下来修改每条边的权值\(w(u,v)=w(u,v)+h[u]-h[v]\)

2.dijkstra

在此基础上对每个点跑单源最短路,注意边权已经改变,最后要进行还原

\(d(u,v)=d(u,w)-h[u]+h[v]\)

struct node
{
    ll x, w;
    bool operator < (const node &u)const
    {
        return w == u.w ? x < u.x : w > u.w;
    }
};
vector<node> g[N];

int n, m;

ll h[N], d[N][N];

bool spfa(int st)
{
    //初始化
    for(int i = 1; i <= n; ++ i)h[i] = inf;
    bitset<N> inq;
    queue<int> q;
    vector<int> cnt(n + 1);
    q.push(st);
    inq[st] = true;

    while(!q.empty())
    {
        auto x = q.front();q.pop();inq[x] = false;
        for(const auto &[y, w] : g[x])
        {
            if(h[x] + w < h[y])
            {
                if(++ cnt[y] >= n)return true;
                h[y] = h[x] + w;
                if(!inq[y])q.push(y), inq[y] = true;
            }
        }
    }
    return false;
}

void dijkstra(int st, ll d[])
{
    for(int i = 1; i <= n; ++ i)d[i] = inf;
    priority_queue<node> pq;
    bitset<N> vis;
    pq.push({st, d[st] = 0});
    while(!pq.empty())
    {
        auto x = pq.top().x;pq.pop();
        if(vis[x])continue;
        vis[x] = true;
        for(const auto &[y, w] : g[x])
        {
            if(d[y] > d[x] + w)
            {
                d[y] = d[x] + w;
                pq.push({y, d[y]});
            }
        }
    }

    //还原
    for(int i = 1; i <= n; ++ i)d[i] = d[i] - h[st] + h[i];
}

void solve()
{
    cin >> n >> m;
    for(int i = 1; i <= m; ++ i)
    {
        ll u, v, w;cin >> u >> v >> w;
        g[u].push_back({v, w});
    }
    //1.建立虚拟原点
    for(int i = 1; i <= n; ++ i)g[0].push_back({i, 0}), h[i] = inf;

    //2.Bellman-Ford求0点到所有点的最短路,作为势能h[]
    if(spfa(0))
    {
        cout << "Ciallo~" << '\n';
        return;
    }

    //3.改造所有边
    for(int x = 1; x <= n; ++ x)
    {
        for(auto &[y, w] : g[x])w = w + h[x] - h[y];
    }

    //4.跑n次dijkstra
    for(int i = 1; i <= n; ++ i)dijkstra(i, d[i]);

    int q;cin >> q;
    while(q --)
    {
        int x, y;cin >> x >> y;
        if(d[x][y] > inf / 2)cout << 114514 << '\n';
        else cout << d[x][y] << '\n';
    }
}

最短路3

如果看过提示应该是可以做出来的吧

这里直接给完整代码了

int n, m;
ll d[N];
ll cnt[N];

vector<int> g[N];

void bfs(int st)
{
    memset(d, 0x3f, sizeof d);
    bitset<N> vis;
    queue<int> q;
    q.push(1);
    d[st] = 0, cnt[st] = 1, vis[st] = true;

    while(!q.empty())
    {
        auto x = q.front();q.pop();
        for(const auto &y : g[x])
        {
            if(!vis[y])
            {
                q.push(y);
                vis[y] = true;
                d[y] = d[x] + 1;
                cnt[y] = cnt[x];
            }else if(d[y] == d[x] + 1)
            {
                cnt[y] = cnt[y] + cnt[x];
            }
        }
    }
}

void solve()
{
    cin >> n >> m;
    for(int i = 1; i <= m; ++ i)
    {
        int u, v, w;cin >> u >> v >> w;
        g[u].push_back(v), g[v].push_back(u);
    }
    bfs(1);
    for(int i = 1; i <= n; ++ i)cout << cnt[i] << " \n"[i == n];
}

标签:大试,int,题解,cnt,st,蓝桥,vis,push,true
From: https://www.cnblogs.com/xaviertse/p/18065486

相关文章

  • LeetCode 128.最长连续序列 Python题解
    leetcode128题最长连续序列分享解题思路,使用哈希表算法......
  • 蓝桥杯算法集训 - Week1:二分、前缀和、差分算法
    蓝桥杯算法集训-Week1本系列随笔用于整理AcWing题单——《蓝桥杯集训·每日一题2024》的系列题型及其对应的算法模板。一、二分查找二分算法原理复习参考:二分查找-Hello算法Ⅰ、二分模板boolcheck(intx){/*...*/}//检查x是否满足某种性质//区间[l,r]被划分......
  • 蓝桥杯备赛第一天 分糖果
    #include<bits/stdc++.h>usingnamespacestd;intmain(){//请在此输入您的代码intn;cin>>n;ints=0;inta[101];//getchar();for(inti=0;i<n;i++){cin>>a[i];}while(1){intc[101];for(inti=0;i<n;i++){......
  • 2024年3月10号题解
    299.猜数游戏解题思路对出现的数字在两个数组中进行统计先计算公牛的个数,如果有那么统计的数字的数量对应减一,因为统计是用来算奶牛的数量的遍历统计数组,奶牛的数量加上两个数组中最小的值,因为是匹配,所以不可能多出来的也可以匹配,所以是加上其中的最小值代码实现intmin(i......
  • P8599 [蓝桥杯 2013 省 B] 带分数
    题目知识点:全排列加指针划分数组。链接:https://www.luogu.com.cn/problem/P8599#include<iostream>#include<vector>#include<algorithm>#include<math.h>#include<sstream>#include<string>#include<string.h>#include<iomanip>#......
  • 常见问题解决 --- 海康OpenAPI安全认证库的demo运行报错
    我要开发一个对接海康isc平台的oss的api,发现需要有海康登录库和ak、sk的配合才能完成。在海康官方下载OpenAPI安全认证库(JAVA)V1.1.11,解压后用idea打开demo发现一对报错。解决办法:1.修复基本的错误。比如包名报错,应该是  packagega; 2.修复maven依赖导入报错。首先是artem......
  • [省选联考 2024] 重塑时光 题解
    考虑这题是什么意思,其实就是让你把DAG划分成若干个集合,点之间连边转化为对应集合之间连边以后图仍然是一个DAG,然后需要知道划分成了多少个集合,每种集合的个数求出方案数,乘上对应的系数并求和。系数是很显然的,即:\[{k+1\choosei}\frac{i!k!}{n!\prod_{i=1}^k(n+i)}\]考虑怎......
  • [省选联考 2024] 迷宫守卫 题解
    首先Bob肯定是贪心操作,即如果能操作且右儿子中第一个数小于左儿子中的第一个数就一定操作(因为排列中的数两两不同),否则不操作。考虑一个dp,即\(f_{i,j}\)表示\(i\)中的子树操作完以后使得第一个数为\(j\)的最小代价。发现总状态数是\(\mathcalO(2^nn)\)的,对于一个点的......
  • [省选联考 2024] 魔法手杖 题解
    首先有个很显然的\(\mathcalO(nk^2)\)的做法,即二分答案,然后trie树上判断。对于trie树上一颗子树内的判定,考虑当前二分的\(\text{mid}\)这一位是\(1\)还是\(0\)以及\(x\)这一位填什么。对于\(1\)的情况,如果填\(0\),那么右儿子仍然合法,左儿子中的数必须要放到......
  • [省选联考 2024] 季风 题解
    \(\large\textbf{Statement.}\)求出最小的非负整数\(m\),使得:\[\left|x-\sum_{i=0}^{m-1}x_{i\bmodn}\right|+\left|y-\sum_{i=0}^{m-1}y_{i\bmodn}\right|\lemk\]\(\large\textbf{Solution.}\)考虑枚举\(m\bmodn\),然后求和就转化成了一段前缀和加上整个序列和的若......