1. 程式人生 > 實用技巧 >G. Reducing Delivery Cost 最短路+暴力列舉

G. Reducing Delivery Cost 最短路+暴力列舉

傳送門

分析

有點像次小生成樹的樸素做法

首先我們用spfa預處理一下任意兩點之間的最短距離,然後列舉圖中任意兩條邊,把這條邊的權值變成0,然後計算通過這條邊的最短路即可

程式碼

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <cstring>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC option("arch=native","tune=native","no-zero-upper")
#pragma GCC target("avx2")
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
const int INF = 0x3f3f3f3f;
const int N = 1e3 + 10,M = 2 * N;
int h[N],ne[M],e[M],w[M],idx;
int d[N];
bool st[N];
int f[N][N];
int n,m,k;
int x[N],y[N];

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

void spfa(int S){
    memset(d,0x3f,sizeof d);
    memset(st,false,sizeof st);
    d[S] = 0;
    queue<int> Q;
    Q.push(S);
    while(Q.size()){
        int t = Q.front();
        Q.pop();
        st[t] = false;
        for(int i = h[t];~i;i = ne[i]){
            int j = e[i];
            if(d[j] > d[t] + w[i]){
                d[j] = d[t] + w[i];
                if(!st[j]){
                    st[j] = true;
                    Q.push(j);
                }
            }
        }
    }
    for(int i = 1;i <= n;i++)
        f[S][i] = d[i];
    f[S][S] = 0;
}


int main(){
    scanf("%d%d%d",&n,&m,&k);
    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);
    }
    for(int i = 1;i <= n;i++)
        spfa(i);
    int ans = 0x3f3f3f3f;
    for(int i = 0;i < k;i++)
        scanf("%d%d",&x[i],&y[i]);
    for(int u = 1;u <= n;u++){
        for(int i = h[u];~i;i = ne[i]){
            int sum = 0;
            for(int j = 0;j < k;j++)
                sum += min(f[x[j]][y[j]],min(f[x[j]][u] + f[y[j]][e[i]],f[x[j]][e[i]] + f[y[j]][u]));
            ans = min(ans,sum);
        }
    }
    printf("%d\n",ans);
    return 0;
}