训练指南 UVA - 11478(最短路BellmanFord+ 二分+ 差分约束)


layout: post
title: 训练指南 UVA - 11478(最短路BellmanFord+ 二分+ 差分约束)
author: "luowentaoaa"
catalog: true
mathjax: true
tags:
- 最短路
- BellmanFord
- 图论
- 训练指南
- 差分约束


Halum

UVA - 11478

题意

带权有向图,每个点都可以有如下操作:令从ta出发的每一条边增加d,终止于ta的每一条边减小d
最后让所有边权的最小值非负且尽量大

题解

考虑每条边的约束,di表示i的halum量

w-dv+du>0

dv-du<w

但求解这个差分约束系统只是让这组不等式成立,最长路和最短路控制的都是单个d的最值而不是最小值最大

那如何最小值最大呢?

二分答案......

那么不等式变为dv-du<w-mid,成立的话说明经过操作后边权可以都比mid大

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=2700+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
struct Edge
{
    int from, to;
    int dist;
    Edge() {}
    Edge(int u, int v, int d) : from(u), to(v), dist(d) {}
};
struct BellmanFord{
    int n,m;
    vector<Edge>edges;
    vector<int> G[maxn];
    bool inq[maxn]; /// 是否在队列中
    int d[maxn];    /// s到各个点的距离  double 要改成double类型
    int p[maxn];    /// 最短路中的上一条弧
    int cnt[maxn];  /// 进队次数
    void init(int n){
        this->n=n;
        for(int i=0;i<n;i++)G[i].clear();
        edges.clear();
    }
    void AddEdge(int from, int to, int dist)
    {
        edges.emplace_back(from, to, dist);
        m = edges.size();
        G[from].push_back(m - 1);
    }
    bool bellmanford(int s){
        queue<int>Q;
        memset(inq,0,sizeof(inq));
        memset(cnt,0,sizeof(cnt));
        for(int i = 0; i < n; i++) { d[i] = 0; inq[0] = true; Q.push(i); } ///如果只判负环用这个
        //for(int i=0;i<n;i++)d[i]=inf;
        //d[s]=0;inq[s]=true;Q.push(s);
        while(!Q.empty()){
            int u=Q.front();
            Q.pop();
            inq[u]=false;
            for(auto& id:G[u]){
                Edge& e=edges[id];
                if(d[u]<inf && d[e.to]>d[u]+e.dist){
                    d[e.to]=d[u] + e.dist;
                    p[e.to]=id;
                    if(!inq[e.to]){
                        Q.push(e.to);
                        inq[e.to]=true;
                        if(++cnt[e.to]>n)return true;
                    }
                }
            }
        }
        return false;
    }
};
BellmanFord solver;
bool test(int x){
    for(int i=0;i<solver.m;i++)
        solver.edges[i].dist-=x;
    bool ret=solver.bellmanford(0);
    for(int i=0;i<solver.m;i++)
        solver.edges[i].dist+=x;
    return !ret;
}
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int n,m;
    while(cin>>n>>m){
        solver.init(n);
        int ub=0;
        while(m--){
            int u,v,d;
            cin>>u>>v>>d;ub=max(ub,d);
            solver.AddEdge(u-1,v-1,d);
        }
        if(test(ub+1))cout<<"Infinite"<<endl;
        else if(!test(1))cout<<"No Solution"<<endl;
        else{
            int l=2,r=ub,ans=1;
            while(l<=r){
                int mid=(l+r)/2;
                if(test(mid)){ans=mid;l=mid+1;}
                else r=mid-1;
            }
            cout<<ans<<endl;
        }
    }
    return 0;
}

转载于:https://www.cnblogs.com/luowentao/p/10348791.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 最短路算法是指在加权图中找到从一个顶点到另一个顶点的最短路径的算法。Matlab中有多种实现最短路算法的方式,其中一种比较常用的是Dijkstra算法。下面是使用Matlab实现Dijkstra算法的示例代码。 假设有一个加权无向图,其中有5个顶点V={1, 2, 3, 4, 5}和8条边E={(1,2,10),(1,3,20),(2,3,30),(2,4,15),(3,4,5),(3,5,25),(4,5,20),(5,1,5)},其中每条边的三个元素分别表示起始顶点、终止顶点和边的权重。现在需要求从顶点1到其他各个顶点的最短路径。 ```matlab % 构建邻接矩阵 n = 5; % 图的顶点数 m = 8; % 图的边数 G = inf(n); % 初始化邻接矩阵 for i = 1:n G(i,i) = 0; % 对角线上的元素为0 end for i = 1:m u = E(i,1); % 边的起始顶点 v = E(i,2); % 边的终止顶点 w = E(i,3); % 边的权重 G(u,v) = w; G(v,u) = w; % 对称矩阵 end % Dijkstra算法求最短路径 dist = inf(1,n); % 到各个顶点的距离 dist(1) = 0; % 起始点的距离为0 visited = zeros(1,n); % 标记是否访问过 for i = 1:n-1 % 找到距离起点最近的顶点 min_dist = inf; for j = 1:n if ~visited(j) && dist(j) < min_dist u = j; min_dist = dist(j); end end visited(u) = 1; % 标记已访问 % 更新与u相邻的顶点的距离 for v = 1:n if ~visited(v) && G(u,v) < inf new_dist = dist(u) + G(u,v); if new_dist < dist(v) dist(v) = new_dist; end end end end % 输出最短路径 for i = 1:n fprintf('从1到%d的最短距离为:%d\n', i, dist(i)) end ``` 输出结果为: ``` 从1到1的最短距离为:0 从1到2的最短距离为:10 从1到3的最短距离为:20 从1到4的最短距离为:25 从1到5的最短距离为:5 ``` ### 回答2: 最短路算法是一种用于查找网络中两个节点之间最短路径的方法。在Matlab中,我们可以使用图算法工具箱(Graph Algorithm Toolbox)中的函数来实现最短路算法。 一种常用的最短路算法是Dijkstra算法,它适用于没有负权边的图。在Matlab中,我们可以使用函数dijkstra来计算最短路径。这个函数需要输入一个表示图的邻接矩阵,以及起点和终点的索引。邻接矩阵中,矩阵元素a(i,j)表示节点i到节点j之间的权值,如果节点i和节点j之间没有边,则a(i,j)设为无穷大。 另一种常用的最短路算法是Bellman-Ford算法,它可以处理带有负权边的图。在Matlab中,我们可以使用函数bellmanford来计算最短路径。这个函数需要输入一个表示图的邻接矩阵,以及起点和终点的索引。类似于dijkstra函数中的邻接矩阵,Bellman-Ford算法也将矩阵中的无穷大设为节点之间没有边。 使用Matlab的最短路算法可以帮助我们解决许多实际问题,例如在交通网络中求解最短驾驶路径或计算电力网络中的最短传输路径。同时,我们还可以通过可视化结果来更好地理解网络中节点和边之间的关系。 ### 回答3: 最短路径算法是图论中的一个重要算法,用于在图中找到从起点到终点的最短路径。其中,Matlab作为一种强大而灵活的编程语言,常常被用来实现算法的计算和可视化。 在Matlab中,可以使用图论工具箱提供的函数来实现最短路径算法。其主要步骤如下: 1. 构建图:首先,需要使用图论工具箱的函数创建一个有向图或无向图,并根据实际需求定义节点和边。可以使用函数`graph()`或`digraph()`来构建图。 2. 定义权重:根据实际情况,需要为图的边指定权重。可以使用函数`addedge()`或`addedge()`为图的每条边添加权重。 3. 寻找最短路径:使用函数`shortestpath()`或`shortestpathtree()`来计算从起点到终点的最短路径。这些函数使用Dijkstra算法或Floyd-Warshall算法进行计算。 4. 可视化结果:使用Matlab的绘图工具,如`plot()`或`plotgraph()`函数,将图和最短路径可视化出来,便于观察和分析结果。 需要注意的是,在使用Matlab实现最短路径算法时,可以根据具体需求选择合适的算法和函数,并对算法的输入参数进行适当调整,以达到最佳的计算效果。另外,还可以结合其他的Matlab功能,如处理大规模图的函数、并行计算等,来提高算法的执行效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值