題目大意:
給定n個點,m條邊的無向圖, 定義c爲任意兩點間的最短路之和,
即
求初始時的c與刪去任意一條邊後的c’的最大值。
分析:
對於最初始時的c, 我們可以通過每次計算以某個點爲源點的最短路徑,不難發現,每次計算後的距離和就是初始值c。
每一次進行刪邊操作時,就可以枚舉每一條邊進行決策:刪除或者不刪除,對於刪除的邊,如果它不在以某個點爲源點的Dijkstra樹上,那麼刪除它對於最短路徑的長度就不會造成影響,所以我們可以忽略它,直接利用上一次計算初始c值時的答案即可。這樣可以使時間複雜度變得可以令人接受。
代碼:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100 + 10;
const int inf = 0x7fffffff;
struct edge { int from, to, dist; };
struct Heapnode {
int d, u;
bool operator < (const Heapnode& rhs) const {
return d > rhs.d;
}
};
struct Dijkstra {
int n, m;
vector<edge> edges;
vector<int> G[maxn];
bool done[maxn];
int dis[maxn], pre[maxn];
void init(int n) {
this->n = n;
for(int i=0; i<n; i++) G[i].clear();
edges.clear();
}
void add_edge(int from, int to, int dist) {
edges.push_back((edge){from, to, dist});
m = edges.size();
G[from].push_back(m-1);
}
//get the single-source shortest path from s
void dijkstra(int s) {
priority_queue<Heapnode> q;
for(int i=0; i<n; i++) dis[i] = inf; dis[s] = 0;
memset(done, false, sizeof(done));
q.push((Heapnode){0, s});
while(!q.empty()) {
Heapnode x = q.top(); q.pop();
int u = x.u; if(done[u]) continue; done[u] = true;
for(int i=0; i<(int)G[u].size(); i++) {
edge& e = edges[G[u][i]];
if(e.dist > 0 && dis[e.to] > dis[u] + e.dist) {
dis[e.to] = dis[u] + e.dist;
pre[e.to] = G[u][i];
q.push((Heapnode){dis[e.to], e.to});
}
}
}
}
}Dij;
int n, m, L, u, v, w;
vector<int> gr[maxn][maxn];
bool used[maxn][maxn][maxn]; // in the shortest path from src, the edge u->v wheather or not used
int idx[maxn][maxn]; //the number in the Dij structure
int sum_single[maxn];
int compute_c() {
int ans = 0;
memset(used, false, sizeof(used));
for(int src=0; src < n; src++) {
Dij.dijkstra(src);
sum_single[src] = 0;
for(int i=0; i<n; i++) {
if(i != src) {
int fa = Dij.edges[Dij.pre[i]].from;
used[src][i][fa] = used[src][fa][i] = 1;
}sum_single[src] += Dij.dis[i] == inf ? L : Dij.dis[i];
}ans += sum_single[src];
}
return ans;
}
int compute_newc(int a, int b) {
int ans = 0;
for(int src=0; src < n; src++) {
if(!used[src][a][b]) ans += sum_single[src];
else {
Dij.dijkstra(src);
for(int i=0; i<n; i++)
ans += Dij.dis[i] == inf ? L : Dij.dis[i];
}
}
return ans;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.txt", "r", stdin);
freopen("ans.txt", "w", stdout);
#endif
while(scanf("%d%d%d", &n, &m, &L) == 3 && n) {
Dij.init(n);
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
gr[i][j].clear();
for(int i=0; i<m; i++) {
scanf("%d%d%d", &u, &v, &w); u--, v--;
gr[u][v].push_back(w);
gr[v][u].push_back(w);
}
for(int i=0; i<n; i++)
for(int j=i+1; j<n; j++) if(!gr[i][j].empty()) {
sort(gr[i][j].begin(), gr[i][j].end());
Dij.add_edge(i, j, gr[i][j][0]);
idx[i][j] = Dij.m - 1;
Dij.add_edge(j, i, gr[i][j][0]);
idx[j][i] = Dij.m - 1;
}
int c = compute_c();
int c1 = -1;
for(int i=0; i<n; i++)
for(int j=i+1; j<n; j++) if(!gr[i][j].empty()) {
int& e1 = Dij.edges[idx[i][j]].dist;
int& e2 = Dij.edges[idx[j][i]].dist;
if(gr[i][j].size() == 1) e1 = e2 = -1;
else e1 = e2 = gr[i][j][1];
c1 = max(c1, compute_newc(i, j));
e1 = e2 = gr[i][j][0];
}
printf("%d %d\n", c, c1);
}
return 0;
}