Question:
The graph of n (2000) points shows its shortest path matrix. A graph with n edges meeting the shortest path matrix is constructed to ensure that the graph is connected and the solution exists.
Ideas:
We can first ensure that graph connectivity requires n-1 sides to associate them with the minimum spanning tree ??
It can be assumed that the abc point has been connected, and now it is considered to be added to a point in the connected block. For example, if d-B is the shortest distance from d to abc, then this edge must be if you do not select d-B, if you choose d-a, then d-a is longer than d-B, so the distance between d-B will never be satisfied.
In this way, we can select n-1 edge based on the minimum spanning tree. Then we want to know if the shortest path matrix is satisfied. If we can add a duplicate edge, we can use dfs. to calculate the shortest path of n-1 edges, because Floyd requires n ^ 3)
If not, what side should we add ?? It is easy to think that the edge with the smallest difference between the new matrix and the original matrix is the proof to be added. It is similar to the above. If we do not add the smallest value, even if we add the smallest value, the smallest value will not be satisfied.
Code:
# Include <cstdio> # include <iostream> # include <cstring> # include <string> # include <algorithm> # include <map> # include <set> # include <vector> # include <queue> # include <cstdlib> # include <ctime> # include <cmath> using namespace std; # define N 2010 # define inf (1 <30) int n, first = 1; int maz [N] [N], dis [N], vis [N], link [N]; int f [N] [N]; int head [N], tot; struct edge {int u, v, w, next ;} ed [N * 2]; void add (int u, int v, int w) {Ed [tot]. u = u; ed [tot]. v = v; ed [tot]. w = w; ed [tot]. next = head [u]; head [u] = tot ++;} void dfs (int now, int start, int len) {for (int I = head [now]; ~ I; I = ed [I]. next) {int v = ed [I]. v; if (! Vis [v]) {vis [v] = 1; f [start] [v] = len + ed [I]. w; dfs (v, start, f [start] [v]) ;}} int main () {while (~ Scanf ("% d", & n) {if (first) first = 0; elseputs (""); for (int I = 1; I <= n; I ++) {for (int j = 1; j <= n; j ++) scanf ("% d", & maz [I] [j]);} for (int I = 1; I <= n; I ++) {vis [I] = 0; dis [I] = inf; link [I] =-1; head [I] =-1;} tot = 0; dis [1] = 0; memset (f, 0, sizeof (f); for (int I = 1; I <= n; I ++) {int pos, near = inf; for (int j = 1; j <= n; j ++) if (! Vis [j] & near> dis [j]) {pos = j; near = dis [j];} if (link [pos]! =-1) {printf ("% d \ n", link [pos], pos, maz [pos] [link [pos]); add (pos, link [pos], maz [pos] [link [pos]); add (link [pos], pos, maz [pos] [link [pos]);} vis [pos] = 1; for (int j = 1; j <= n; j ++) {if (! Vis [j] & dis [j]> maz [pos] [j]) {link [j] = pos; dis [j] = maz [pos] [j] ;}} int a, B, c = inf; for (int I = 1; I <= n; I ++) {for (int j = 1; j <= n; j ++) vis [j] = 0; vis [I] = 1; dfs (I, i, 0); for (int j = 1; j <= n; j ++) {if (maz [I] [j] <f [I] [j] & c> maz [I] [j]) {a = I; B = j; c = maz [I] [j] ;}} if (c = inf) a = ed [0]. u, B = ed [0]. v, c = ed [0]. w; printf ("% d \ n", a, B, c);} return 0 ;}
UVALive 6622 Absurdistan Roads