题意:①先求任意两点间的最短路径累加和,其中不连通的边权为L ②删除任意一条边,求全局最短路径和的最大值。
解题报告:由于要求[多源最短路][路径和],我们首先可以想到[Floyed],但是有删边的操作,所以[Floyed]时间复杂度为O(n*n*n*m), 直接跑dijkstra复杂度为o(n*m*m*logn), 复杂度也很大,所以我们可以使用[最短路树],只有要删的边在树上时,我们才需要重新跑[dijkstra],由于树上有n-1条边,所以复杂度为o(n*n*m*logn);
ps:要开long long
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 105;
const int M = 1000;
const long long Inf = 1e12 + 7;
#define LL long long
LL l;
struct Edge{
int u, v, w, id;
Edge(int u,int v,int w,int id):u(u),v(v),w(w),id(id){}
};
struct HeapNode{
LL dist;
int u;
bool operator<(const HeapNode& rhs) const{
return dist>rhs.dist;
}
};
struct Dijkstra{
int n, m;
vector<Edge> edges;
vector<int> G[N];
LL d[N], ans, ret, dt[N];
bool done[N];
int p[N], link[M][N], del[M];
void init(int n){
memset(dt,0,sizeof(dt));
memset(link,0,sizeof(link));
ans=ret=0;
this->n=n;
for ( int i=1; i<=n; i++ ) G[i].clear();
edges.clear();
}
void addeage(int u, int v, int w, int id){
edges.push_back(Edge(u,v,w,id));
m=edges.size();
G[u].push_back(m-1);
}
void dijkstra1(int s){
for ( int i=1; i<=n; i++ ) d[i]=Inf, done[i]=p[i]=0;
priority_queue<HeapNode> Q;
Q.push((HeapNode){0,s});
d[s]=0;
while( !Q.empty() ){
HeapNode x=Q.top(); Q.pop();
int u=x.u;
if( done[u] ) continue;
done[u]=1;
link[p[u]][s]=1;
for ( int i=0; i<G[u].size(); i++ ){
Edge& e=edges[G[u][i]];
if( d[e.v]>d[u]+e.w ){
d[e.v]=d[u]+e.w;
p[e.v]=e.id;
Q.push((HeapNode){d[e.v],e.v});
}
}
}
for ( int i=1; i<=n; i++ ){
if( d[i]==Inf ) ans+=l, dt[s]+=l;
else ans+=d[i], dt[s]+=d[i];
}
}
LL dijkstra2(int s){
for ( int i=1; i<=n; i++ ) d[i]=Inf, done[i]=0;
d[s]=0;
priority_queue<HeapNode> Q;
Q.push((HeapNode){0,s});
while( !Q.empty() ){
HeapNode x=Q.top(); Q.pop();
int u=x.u;
if( done[u] ) continue;
done[u]=1;
for ( int i=0; i<G[u].size(); i++ ){
Edge& e=edges[G[u][i]];
if( del[e.id] ) continue;
if( d[e.v]>d[u]+e.w ){
d[e.v]=d[u]+e.w;
Q.push((HeapNode){d[e.v],e.v});
}
}
}
LL tt=0;
for ( int i=1; i<=n; i++ ){
if( d[i]==Inf ) tt+=l;
else tt+=d[i];
}
return tt;
}
};
Dijkstra D;
int main(){
int n, m;
while( scanf("%d%d%lld", &n, &m, &l )==3 ){
D.init(n);
for ( int i=1; i<=m; i++ ){
int u, v, w;
scanf("%d%d%d", &u, &v, &w );
D.addeage(u, v, w, i);
D.addeage(v, u, w, i);
}
for ( int i=1; i<=n; i++ ) D.dijkstra1(i);
for ( int i=1; i<=m; i++ ){
D.del[i]=1;
LL tt=0;
for ( int j=1; j<=n; j++ )
if( D.link[i][j] ) tt+=D.dijkstra2(j);
else tt+=D.dt[j];
D.del[i]=0;
D.ret=max(D.ret,tt);
}
printf("%lld %lld\n", D.ans, D.ret );
}
}