Codeforces1433G Reducing Delivery Cost
阿新 • • 發佈:2020-12-20
Solution
一開始的想法是把所有最短路在途中標記出來,然後取一個 經過次數\(\times\)邊權 最大的邊邊權置為 \(0\),然後就成為了標準錯解,WA ON TEST 2。這是因為刪之前的最短路徑和刪之後的最短路徑不一定重合,這點從樣例二就可以看出來。
令 \(\text{dis}(x,y)\) 表示 \(x\) 到 \(y\) 的最短距離,那麼我們要考慮的就是將一條邊 \((u,v)\) 邊權置零後 \(\text{dis}(a_i,b_i)\) 會如何變化。如果想要讓 \(\text{dis}(a_i,b_i)\) 變小,則最短路徑一定會經過 \((u,v)\) 這條邊。顯然,此時 \(\text{dis}(a_i,b_i)=\min\{\text{dis}(a_i,b_i),\text{dis}(a_i,u)+\text{dis}(b_i,v),\text{dis}(a_i,v)+\text{dis}(b_i,u)\}\)
Code
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> using namespace std; inline void read(int &x) { x=0; int f=1; char c=getchar(); while(c<'0' || c>'9') { if(c=='-') f=-1; c=getchar(); } while(c>='0' && c<='9') { x=(x<<1)+(x<<3)+(c^48); c=getchar(); } x*=f; } const int N=1000,M=2000,INF=0x3f3f3f3f; int head[N+10],ver[M+10],nxt[M+10],edge[M+10],tot=1; void add(int x,int y,int z) { ver[++tot]=y; edge[tot]=z; nxt[tot]=head[x]; head[x]=tot; } int dis[N+10][N+10]; bool vis[N+10]; int n,m,k; void dij(int S) { for(int i=1;i<=n;i++) dis[S][i]=INF; dis[S][S]=0; memset(vis,0,sizeof(vis)); priority_queue<pair<int,int> > que; que.push(make_pair(0,S)); while(!que.empty()) { int x=que.top().second; que.pop(); if(vis[x]) continue; vis[x]=1; for(int i=head[x];i;i=nxt[i]) { int y=ver[i],z=edge[i]; if(dis[S][x]+z<dis[S][y]) { dis[S][y]=dis[S][x]+z; que.push(make_pair(-dis[S][y],y)); } } } } struct node { int a,b; // bool operator < (const node &x) const {return a==x.a?b<x.b:a<x.a;} // bool operator == (const node &x) const {return a==x.a && b==x.b;} }s[N+10]; int U[N+10],V[N+10]; int main() { read(n);read(m);read(k); for(int i=1;i<=m;i++) { int u,v,w; read(u);read(v);read(w); U[i]=u;V[i]=v; add(u,v,w); add(v,u,w); } for(int i=1;i<=n;i++) dij(i); for(int i=1;i<=k;i++) { read(s[i].a); read(s[i].b); } // sort(s+1,s+k+1); // k=unique(s+1,s+k+1)-s-1; int ans=INF; for(int i=1;i<=m;i++) { int sum=0; for(int j=1;j<=k;j++) sum+=min(dis[s[j].a][s[j].b],min(dis[s[j].a][U[i]]+dis[V[i]][s[j].b],dis[s[j].a][V[i]]+dis[U[i]][s[j].b])); ans=min(ans,sum); } printf("%d",ans); return 0; }