题目链接:https://icpcarchive.ecs.baylor.edu/external/40/4080.pdf
题意:有n个顶点,m条边,path[i][j]表示从i到j的最短路径,如果从i到j不连通,则path[i][j] = L;现在求
然后删除一条边,求c1,使得c1 - c 的值最大。
思路:刚看到题目是让各点之间的最短路径和,所以立马想到啦floyd算法求最短路,然后发现还要去掉一条边后求最短路中的最大值,则floyd会超时,所以打算用dijkstra+堆优化做,首先枚举n个顶点求各个顶点之间的最短路径,并求出最短路树,然后枚举每条边,如果这条边在最短路树中,则再求一遍该点的最短路径即可,如果不在最短路树中,则直接利用第一次求得最短路即可。
所谓的最短路树是指在求最短路的同时,记录最短路径。
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#define LL long long
#define inf 1LL << 50
using namespace std;
const int maxn = 110;
const int maxp = 4e3 + 10;
int head[maxp],n,m,L,cnt,vis[maxn],belong[maxp][maxn],p[maxn],delt[maxp];
LL sum[maxn],dist[maxn];//belong[][]记录以s为原点的第i条边是否在s的最短路径中
struct Edge{
int to,next,w,id;
}edge[maxp];
struct HeapNode{
int dist,v;
friend bool operator <(HeapNode A, HeapNode B){
return A.dist > B.dist;
}
};
void add(int u, int v, int w, int i){
edge[cnt].to = v;
edge[cnt].id = i;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt ++;
}
void dijkstra(int x){
for(int i = 0; i <= n; i ++) dist[i] = inf, vis[i] = 0;
memset(p,0,sizeof(p));
dist[x] = 0;
priority_queue<HeapNode> q;
HeapNode no;
no.dist = 0; no.v = x;
q.push(no);
while(!q.empty()){
no = q.top(); q.pop();
if(vis[no.v]) continue;
belong[p[no.v]][x] = 1;
vis[no.v] = 1;
for(int i = head[no.v]; i != -1; i = edge[i].next){
int v = edge[i].to;
if(dist[v] > dist[no.v] + edge[i].w){
dist[v] = dist[no.v] + edge[i].w;
HeapNode hn;
p[v] = edge[i].id;
hn.dist = dist[v]; hn.v = v;
q.push(hn);
}
}
}
for(int i = 1; i <= n; i ++){
if(dist[i] == inf) sum[x] += L;
else sum[x] += dist[i];
}
}
int dij(int x){
for(int i = 0; i <= n; i ++) dist[i] = inf, vis[i] = 0;
dist[x] = 0;
priority_queue<HeapNode> q;
HeapNode no;
no.dist = 0; no.v = x;
q.push(no);
while(!q.empty()){
no = q.top(); q.pop();
if(vis[no.v]) continue;
vis[no.v] = 1;
for(int i = head[no.v]; i != -1; i = edge[i].next){
if(delt[edge[i].id]) continue;
int v = edge[i].to;
if(dist[v] > dist[no.v] + edge[i].w){
dist[v] = dist[no.v] + edge[i].w;
HeapNode hn;
hn.dist = dist[v]; hn.v = v;
q.push(hn);
}
}
}
int ans = 0;
for(int i = 1; i <= n; i ++){
if(dist[i] == inf) ans += L;
else ans += dist[i];
}
return ans;
}
int main(){
while(~scanf("%d%d%d",&n,&m,&L)){
cnt = 0;
int u,v,w;
memset(head,-1,sizeof(head));
for(int i = 1; i <= m; i ++){
scanf("%d%d%d",&u,&v,&w);
add(u,v,w,i);
add(v,u,w,i);
}
memset(belong,0,sizeof(belong));
for(int i = 1; i <= n; i ++){
sum[i] = 0;
dijkstra(i);
}
LL ans = 0, Max = 0;
memset(delt,0,sizeof(delt));
for(int i = 1; i <= n; i ++) ans += sum[i];
for(int i = 1; i <= m; i ++){
delt[i] = 1;
LL tmp = 0;
for(int j = 1; j <= n; j ++){
if(belong[i][j]) tmp += dij(j);
else tmp += sum[j];
}
delt[i] = 0;
Max = max(Max,tmp);
}
printf("%lld %lld\n",ans,Max);
}
return 0;
}