G. Reducing Delivery Cost 思維+最短路
阿新 • • 發佈:2020-10-23
G. Reducing Delivery Cost 思維+最短路
題目大意:
n個點,m條邊,q條路經,每條路徑有一個起點一個終點,你最多可以選擇刪掉一條邊,問刪完之後q條路經距離的最小值之和,距離表示起點到終點的最短距離。
題解:
先預處理任意兩個點之間的最短距離,列舉這m條邊,查刪掉之後的距離,求最小值。
注意:如果一條邊刪去,那麼最短距離的更新有兩種可能
- 刪掉前後都不是最短距離的一部分,最短距離不變
- 刪掉之後成為了最短距離的一部分,那麼就是原來的點到兩端的距離+0
最後的複雜度就是 \(O(n*m+m*k*logn)\)
這個題目主要要明白,一條邊變成0之後,應該如何更新這個最短路。
#include <bits/stdc++.h> #define inf 0x3f3f3f3f #define inf64 0x3f3f3f3f3f3f3f3f using namespace std; const int maxn = 1010; typedef long long ll; int head[maxn],flag[maxn<<1],to[maxn<<1],nxt[maxn<<1],cnt,cost[maxn],w[maxn<<1]; void add(int u,int v,int i,int c){ ++cnt,to[cnt] = v,flag[cnt] = i,nxt[cnt] = head[u],w[cnt] = c,head[u] = cnt; ++cnt,to[cnt] = u,flag[cnt] = i,nxt[cnt] = head[v],w[cnt] = c,head[v] = cnt; } struct node{ int u,d; node(int u=0,int d=0):u(u),d(d){} bool operator<(const node&a)const{ return a.d<d; } }; int vis[maxn],d[maxn][maxn],n,m,k,num[maxn]; priority_queue<node>que; void dij(int s){ int pos = s; while(!que.empty()) que.pop(); for(int i=1;i<=n;i++) d[pos][i] = inf,vis[i] = false; que.push(node(s,0)); d[pos][s] = 0; while(!que.empty()){ node x = que.top();que.pop(); int u = x.u; if(vis[u]) continue; vis[u] = true; for(int i=head[u];i;i=nxt[i]){ int v = to[i]; if(d[pos][v]>d[pos][u]+w[i]){ d[pos][v] = d[pos][u] + w[i]; que.push(node(v,d[pos][v])); } } } } int gx[maxn],gy[maxn],ux[maxn],uy[maxn],uw[maxn]; int main(){ scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=m;i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,i,w); cost[i] = w,ux[i] = u,uy[i] = v,uw[i] =w; } for(int i=1;i<=k;i++){ scanf("%d%d",&gx[i],&gy[i]); dij(gx[i]),dij(gy[i]); } ll ans = inf64; for(int i=1;i<=m;i++){ ll sum = 0; int x = ux[i],y = uy[i],w = uw[i]; for(int j=1;j<=k;j++){ int u = gx[j],v = gy[j]; sum += min(min(d[u][x]+d[v][y],d[u][y]+d[v][x]),d[u][v]); } ans = min(ans,sum); } printf("%lld\n", ans); return 0; }