G. Reducing Delivery Cost 最短路+暴力列舉
阿新 • • 發佈:2020-10-21
傳送門
分析
有點像次小生成樹的樸素做法
首先我們用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; }