CodeForces 449B Jzzhu and Cities(最短路)

本文介绍了一种Dijkstra算法的变种应用案例,在给定的无向图中找到最多可删除的边数,使从特定节点出发到达其它各节点的最短路径长度保持不变。该方法首先使用特定的边集预更新距离数组,随后执行Dijkstra算法以确定哪些边可以被舍弃。
题目连接
题意

给你一个由n个点m条边组成的无向图,再给你k条边(起点必为1),再k条边中求最多能删掉几条边,使得1到各个点的最短路大小不变。

思路

Dijkstra 变形,dis数组初始化正无穷,可以直接用k条边先更新dis数组(因为起点必为1),然后将当前所有起点据终点长度不为正无穷的入队(1号点先入队),修改dijkstra中判断,如果当前点是第一次能够缩短,且不为正无穷说明铁路能够舍去。

代码
#include <bits/stdc++.h>
using namespace std;

#define _p pair<int, int>

const int N = 100005;

int n, m, k, ans = 0;

vector<_p> e[N];
int vis[N], dis[N], flag[N];
priority_queue<_p, vector<_p>, greater<_p> > q;

void dij()
{
    while(!q.empty())
    {
        _p u = q.top();
        q.pop();
        if(vis[u.second]) continue;
        vis[u.second] = 1;
        for(auto v : e[u.second])
        {
            if(dis[v.second] >= dis[u.second]+v.first)
            {
                if(flag[v.second] == 0 && dis[v.second] != 0x3f3f3f3f) ++ans;
                flag[v.second] = 1;
                dis[v.second] = dis[u.second]+v.first;
                q.push({dis[v.second], v.second});
            }
        }
    }
}

int main() {
    scanf("%d%d%d",&n,&m,&k);
    while(m--)
    {
        int u, v, w;
        scanf("%d%d%d",&u,&v,&w);
        e[u].push_back({w,v});
        e[v].push_back({w,u});
    }
    memset(vis,0,sizeof(vis));
    memset(dis,0x3f,sizeof(dis));
    for(int i = 1; i <= k; ++i) {
        int v, w;
        scanf("%d%d",&v,&w);
        if(dis[v] != 0x3f3f3f3f) ++ans;
        dis[v] = min(dis[v], w);
    }
    dis[1] = 0;
    for(int i = 1; i <= n; ++i) if(dis[i] != 0x3f3f3f3f) q.push({dis[i], i});
    dij();
    printf("%d\n",ans);
    return 0;
}
### Codeforces 平台上的短路径算法题目 #### Dijkstra 算法的应用实例 当面对构建短路径树的需求时,可以采用Dijkstra算法来解决。该方法的核心在于优先选择当前节点能够延伸出去的多条候选边中具有小权重的一条作为扩展方向;而在仅存在唯一一条可能的拓展边的情况下,则直接选取这条边继续探索过程[^1]。 ```python import heapq def dijkstra(graph, start): n = len(graph) dist = [float('inf')] * n dist[start] = 0 heap = [(0, start)] while heap: current_dist, u = heapq.heappop(heap) if current_dist != dist[u]: continue for v, weight in graph[u].items(): alt = dist[u] + weight if alt < dist[v]: dist[v] = alt heapq.heappush(heap, (alt, v)) return dist ``` #### Floyd-Warshall 算法处理复杂情况下的优化策略 对于涉及多个源点之间的短路径计算问题,Floyd-Warshall是一个有效的解决方案。然而,在某些特定场景下(比如本题),通过预先给定的信息可以直接定位受影响的部分并加以简化,从而避免不必要的全量遍历操作,达到降低时间复杂度的效果。值得注意的是,在累加过程中应当选用`long long`类型的变量以防止溢出错误的发生[^2]。 #### 单源短路径查询案例解析 考虑到从指定起点出发前往其余各个顶点间的短距离需求,此情形适用于单源短路径类别的算法实现方式。具体而言,即是从某固定位置开始测量至其它任意可达地点的距离长度,并针对不可达的情形输出特殊标记值 `-1` 表明无法访问的状态[^3]。 ```cpp #include<bits/stdc++.h> using namespace std; const int INF=0x3f3f3f; vector<pair<int,int>> adj[100]; int dis[100]; void spfa(int src){ queue<int> q; vector<bool> vis(100,false); fill(dis,dis+100,INF); dis[src]=0;q.push(src); while(!q.empty()){ int cur=q.front();q.pop(); vis[cur]=false; for(auto& edge : adj[cur]){ int next=edge.first,cost=edge.second; if(dis[next]>dis[cur]+cost){ dis[next]=dis[cur]+cost; if(!vis[next]){ vis[next]=true; q.push(next); } } } } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值