其他分享
首页 > 其他分享> > G - Reducing Delivery Cost -最短路

G - Reducing Delivery Cost -最短路

作者:互联网

G - Reducing Delivery Cost

 题意:

给你n个点和m条边以及每条边的权值 允许让一条边的权值变成0 然后有q次询问 求q次询问的xi到yi的最小路径和

思路:  

显然是最短路的题 但是直接套最短路模板 枚举每条免费的边然后再dij每个点 来求 时间复杂度 是 n* m * k * log(m)会超时

所以就要考虑 先预处理每两个点的最短路 用dis[x][y]储存 后续再枚举每条边 求最短路 

对于一条免费的边有两种情况

#include <bits/stdc++.h> 
#include <queue>
#define ll unsigned long long
#define pi acos(-1)
#define FF ios::sync_with_stdio(false), cin.tie(0)
using namespace std;
const int mod = 1e9 + 7;
const int N = 1e6 + 10;
const int inf = 0x3f3f3f3f;
int  n, m, qq, dis[1010][1010];

struct node{
    int to, w;
};

vector<node> g[N];
vector<pair<int, int> >v; 
int vis[1010], inq[1010];
priority_queue<pair<int ,int>, vector<pair<int ,int> >, greater<pair<int ,int> > >q;
//最短路算法
void dij(int x){
    //初始化
    memset(vis, 0, sizeof(vis));
    memset(inq, 0, sizeof(inq));
    dis[x][x] = 0;//自己到自己值为零
    q.push(make_pair(dis[x][x], x));
    inq[x] = 1;//记录已在队列中
    while(!q.empty()){
        pair<int, int>now = q.top();
        q.pop();
        if(vis[now.second]) continue;
        vis[now.second] = 1;//判断是否已经访问过
        int from = now.second;
        for(int i = 0; i < g[from].size(); i++){
            int to = g[from][i].to;
            int w = g[from][i].w;//注意写法 不要用min函数
            if(dis[x][to] > dis[x][from] + w){
                dis[x][to] = dis[x][from] + w;
                if(!inq[to]) q.push(make_pair(dis[x][to], to));
            }
        }
    }
    
}

int main()
{
    FF; 
    cin >> n >> m >> qq;
    for(int i = 1; i <= m; i++){
        int x, y, w;
        cin >> x >> y >> w;
        g[x].push_back({y, w});
        g[y].push_back({x, w});
    }
    memset(dis, inf, sizeof(dis));//因为是取最小 所以一开始要很大
    for(int i = 1; i <= n; i++){//预处理最短路
        dij(i);
    }
    for(int i = 1; i <= qq; i++){
        int a, b;
        cin >> a >> b;
        v.push_back(make_pair(a, b));
    }
    int anss = inf;
    for(int i = 1; i <= n; i++){
        for(int j = 0; j < g[i].size(); j ++){
            int t = g[i][j].to;
            int ans = 0;
            for(int k = 0; k < v.size(); k++){
                int from = v[k].first, to = v[k].second;
                //直接用ans+= 不要更新dis 不然会出错 比大小的时候不要忘了是三个值比较 容易把dis[from][t]+dis[i][to]忘记
                ans += min({dis[from][to], dis[from][i] + dis[t][to], dis[from][t] + dis[i][to]});
            }
            anss = min(anss, ans);//对于每条免费边答案取最小 
        }
    }
    cout << anss << "\n";
    return 0;
}

 

标签:int,短路,inq,Delivery,vis,Cost,push,Reducing,dis
来源: https://www.cnblogs.com/yaqu-qxyq/p/15975596.html