N cities, ranging from 0 to N-1, M roads, K roads (K starting from 0) are 2 ^ K, returns the shortest distance from a city numbered 0 to another city.
Input: the first line is two positive integers, N (2 <= n <= 100) m (M <= 500), indicating that there are n cities and M roads.
The next two integers in the M line indicate the numbers of the two connected cities. The input data must have no duplicate edges.
Output: N-1 line, indicating the shortest circuit from city 0 to other cities. If not, output-1. The value is too large to output with Mod 100000.
Ideas:
Because the weight of edge I w [I] = 2 ^ I, then the sum of the weight of the edge of the front I-1 is W [0] + W [1] + · + W [I-1] = (2 ^ I)-1
That is to say, the sum of the weights of the first I-1 edge is smaller than that of the first I side.
Based on this nature, when an I-th edge (A, B) is added:
If A and B are not connected, the shortest path between A and B is W [I].
If A and B are connected, the shortest paths between A and B remain unchanged.
#include<cstdio>#include<fstream>using namespace std;#define MAX 550#define INF 9999999#define M 100000int father[MAX], rank[MAX];int d[MAX][MAX];void init ( int n ){ for ( int i = 0; i < n; i++ ) { father[i] = i; rank[i] = 1; d[i][i] = 0; }}int Find ( int i ){ if ( i != father[i] ) father[i] = Find(father[i]); return father[i];}void Union ( int a, int b ){ int ta = Find(a); int tb = Find(b); if ( ta == tb ) return; if ( rank[a] >= rank[b] ) { father[tb] = ta; rank[ta] += rank[tb]; } else { father[ta] = tb; rank[tb] += rank[ta]; }}int mod_exp ( long long a, long long b ){ long long ret = 1; while ( b > 0 ) { if ( b & 1 ) ret = ( ret * a ) % M; b >>= 1; a = ( a * a ) % M; } return ret;}int main(){ int n, m, i, j, k; int a, b, ta, tb, dist; while ( scanf("%d%d",&n,&m) != EOF ) { init(n); for ( k = 0; k < m; k++ ) { scanf("%d%d",&a,&b); ta = Find(a); tb = Find(b); if ( ta == tb ) continue; dist = mod_exp(2,k); for ( i = 0; i < n; i++ ) { if ( Find(i) != ta ) continue; for ( j = 0; j < n; j++ ) { if ( Find(j) != tb ) continue; d[i][j] = (d[i][a] + dist + d[b][j]) % M; d[j][i] = d[i][j]; } } Union(a,b); } ta = Find(0); for ( i = 1; i < n; i++ ) { if ( Find(i) == ta ) printf("%d\n",d[0][i]); else printf("-1\n"); } } return 0;}
Of course, the shortest path can still be obtained using a standard algorithm ···
# Include <cstdio> # include <cstring> # include <algorithm> using namespace STD; # define M 100000 # define INF 1999999 class node {public: int DN [505]; void Init (INT); bool operator <(const node &); bool operator = (const node &); node operator + (const node &); node operator + (INT) ;}; void node: Init (INT flag) {for (INT I = 500; I> = 0; I --) DN [I] = flag? INF: 0;} bool node: Operator <(const node & X) {for (INT I = 500; I> = 1; I --) if (DN [I] <X. DN [I]) return true; else if (DN [I]> X. DN [I]) return false;} bool node: Operator = (const node & X) {for (INT I = 500; I> = 1; I --) if (DN [I]! = X. DN [I]) return false; return true;} node: Operator + (const node & X) {node ret; For (INT I = 500; I> = 1; I --) ret. DN [I] = DN [I] + X. DN [I]; return ret;} node: Operator + (INT X) {node ret = * This; ret. DN [x] ++; return ret;} int map [110] [110], vis [110]; node D [110], mm; void Dijkstra (int n) {node TMP; int I, j, k; for (I = 1; I <= N; I ++) d [I]. init (1), vis [I] = 0; d [1]. init (0); (I = 1; I <= N; I ++) {for (TMP = mm, j = 1; j <= N; j ++) if (! Vis [J] & D [J] <TMP) TMP = d [k = J]; If (TMP = mm) break; vis [k] = 1; for (j = 1; j <= N; j ++) {If (vis [J] | map [k] [J] = inf) continue; TMP = d [k] + map [k] [J]; If (TMP <D [J]) d [J] = TMP ;}}} int mod_exp (long a, long B) {long ret = 1; while (B> 0) {If (B & 1) ret = (Ret *) % m; B> = 1; A = (A * A) % m;} return ret;} int CAL (const node & X) {int sum = 0; fo R (INT I = 1; I <= 500; I ++) {If (X. DN [I] = 0) continue; sum + = x. DN [I] % m * mod_exp (2, I-1); sum % = m;} return sum;} int main () {mm. init (1); int n, m, a, B, I, j; while (scanf ("% d", & N, & M )! = EOF) {for (I = 1; I <= N; I ++) for (j = 1; j <= N; j ++) map [I] [J] = (I = J )? 0: INF; for (I = 1; I <= m; I ++) {scanf ("% d", & A, & B); A ++; B ++; // note that the side is + 1, point + 1. of course, if this is not the case, you can also · map [a] [B] = map [B] [a] = I;} Dijkstra (n); for (I = 2; I <= N; I ++) {If (d [I] = mm) printf ("-1 \ n"); else printf ("% d \ n ", cal (d [I]) ;}} return 0 ;}