29
29
#include < unordered_map>
30
30
#include " utils.h"
31
31
32
+ #include " SquareMatrixMultiply.cpp"
33
+
32
34
#define uset typename std::unordered_set
33
35
#define umap typename std::unordered_map
34
36
@@ -67,6 +69,57 @@ struct EdgeHash {
67
69
}
68
70
};
69
71
72
+ template <typename T>
73
+ class Weight {
74
+ public:
75
+ typedef T value_type;
76
+ Weight (): inf(1 ) {}
77
+ Weight (T x): val(x), inf(0 ) {}
78
+ Weight (T x, int i): val(x), inf(i) {}
79
+ bool operator <(const Weight<T>& rhs) const {
80
+ if (inf || rhs.inf )
81
+ return inf < rhs.inf ;
82
+ else
83
+ return val < rhs.val ;
84
+ }
85
+ bool operator ==(const Weight<T>& rhs) const {
86
+ if (inf || rhs.inf )
87
+ return inf == rhs.inf ;
88
+ else
89
+ return val == rhs.val ;
90
+ }
91
+ Weight<T> operator +(const Weight<T>& rhs) const {
92
+ if (inf + rhs.inf > 0 )
93
+ return Weight<T>(0 , 1 );
94
+ if (inf + rhs.inf < 0 )
95
+ return Weight<T>(0 , -1 );
96
+ assert (!inf && !rhs.inf );
97
+ return Weight<T>(val + rhs.val );
98
+ }
99
+ Weight<T> operator -(const Weight<T>& rhs) const {
100
+ if (inf - rhs.inf > 0 )
101
+ return Weight<T>(0 , 1 );
102
+ if (inf - rhs.inf < 0 )
103
+ return Weight<T>(0 , -1 );
104
+ assert (!inf && !rhs.inf );
105
+ return Weight<T>(val - rhs.val );
106
+ }
107
+ friend std::ostream& operator <<(std::ostream& os, const Weight<T>& rhs){
108
+ switch (rhs.inf ) {
109
+ case -1 :
110
+ return os << " -inf" ;
111
+ case 0 :
112
+ return os << rhs.val ;
113
+ case 1 :
114
+ return os << " inf" ;
115
+ default :
116
+ return os;
117
+ }
118
+ }
119
+ T val;
120
+ int inf;
121
+ };
122
+
70
123
template <typename T>
71
124
class EdgeIteratorAL1 {
72
125
public:
@@ -304,8 +357,103 @@ class GraphAdjMatrix: public Graph<T> {
304
357
umap<T, umap<T, bool >> E;
305
358
};
306
359
360
+ template <typename T, typename WT>
361
+ class WeightedAdjMatrix {
362
+ public:
363
+ WeightedAdjMatrix (bool direction): dir(direction) {}
364
+ bool add_vertex (T u) {
365
+ if (V.find (u) != V.end ())
366
+ return false ;
367
+ V.insert (u);
368
+ for (auto i = V.begin (); i != V.end (); i++) {
369
+ const T& v = *i;
370
+ if (u == v)
371
+ E[u][u] = Weight<WT>(0 );
372
+ else
373
+ E[u][v] = E[v][u] = Weight<WT>();
374
+ }
375
+ return true ;
376
+ }
377
+ void add_edge (T s, T d, WT w) {
378
+ add_vertex (s);
379
+ if (s != d) {
380
+ add_vertex (d);
381
+ E[s][d] = w;
382
+ if (!dir)
383
+ E[d][s] = w;
384
+ }
385
+ }
386
+ bool is_edge (T u, T v) {
387
+ return u != v && !E[u][v].inf ;
388
+ }
389
+ Weight<WT> get_edge (T u, T v) {
390
+ return E[u][v];
391
+ }
392
+ void random_graph (T v, size_t e, WT l, WT h) {
393
+ for (T i = 0 ; i < v; i++)
394
+ add_vertex (i);
395
+ std::vector<T> d;
396
+ std::vector<WT> w;
397
+ random_integers<T>(d, 0 , v - 1 , 2 * e);
398
+ random_integers<WT>(w, l, h, e);
399
+ for (size_t i = 0 ; i < e; i++)
400
+ add_edge (d[2 * i], d[2 * i + 1 ], w[i]);
401
+ }
402
+ template <typename F1, typename F2>
403
+ void graphviz (F1 f1, F2 f2) {
404
+ if (dir)
405
+ std::cout << " digraph G {" << std::endl;
406
+ else
407
+ std::cout << " graph G {" << std::endl;
408
+ std::cout << ' \t ' ;
409
+ for (auto i = V.begin (); i != V.end (); i++) {
410
+ std::cout << *i;
411
+ if (f1 (*i))
412
+ std::cout << " ; \n\t " ;
413
+ else
414
+ std::cout << " ; " ;
415
+ }
416
+ std::cout << std::endl;
417
+ for (auto i = E.begin (); i != E.end (); i++) {
418
+ for (auto j = i->second .begin (); j != i->second .end (); j++) {
419
+ if (i->first != j->first && !j->second .inf &&
420
+ (dir || i->first < j->first )) {
421
+ Edge<T> e (i->first , j->first , dir);
422
+ std::cout << ' \t ' << e;
423
+ std::cout << " [label=\" " << j->second << " \" " ;
424
+ f2 (e, j->second );
425
+ std::cout << " ]; " << std::endl;
426
+ }
427
+ }
428
+ }
429
+ std::cout << " }" << std::endl;
430
+ }
431
+ void graphviz () {
432
+ auto f1 = [](T v) { return false ; };
433
+ auto f2 = [](Edge<T> e, Weight<WT> w) {};
434
+ graphviz (f1, f2);
435
+ }
436
+ void to_matrix (Matrix<Weight<WT>>& ans) {
437
+ const size_t n = V.size ();
438
+ for (size_t i = 0 ; i < n; i++)
439
+ assert (V.find (i) != V.end ());
440
+ ans.cols = ans.rows = n;
441
+ ans.data .reserve (n);
442
+ for (size_t i = 0 ; i < n; i++) {
443
+ MatrixRow<Weight<WT>> row;
444
+ row.reserve (n);
445
+ for (size_t j = 0 ; j < n; j++)
446
+ row.push_back (E[i][j]);
447
+ ans.data .push_back (row);
448
+ }
449
+ }
450
+ bool dir;
451
+ uset<T> V;
452
+ umap<T, umap<T, Weight<WT>>> E;
453
+ };
454
+
307
455
template <typename T>
308
- void random_graph (Graph<T>& G, T v, T e) {
456
+ void random_graph (Graph<T>& G, T v, size_t e) {
309
457
for (T i = 0 ; i < v; i++)
310
458
G.add_vertex (i);
311
459
std::vector<T> d;
@@ -315,7 +463,7 @@ void random_graph(Graph<T>& G, T v, T e) {
315
463
}
316
464
317
465
template <typename T>
318
- void random_dag (Graph<T>& G, T v, T e) {
466
+ void random_dag (Graph<T>& G, T v, size_t e) {
319
467
for (T i = 0 ; i < v; i++)
320
468
G.add_vertex (i);
321
469
std::vector<T> d;
@@ -392,11 +540,29 @@ void graph_test(const size_t v, const size_t e) {
392
540
}
393
541
}
394
542
543
+ template <typename T, typename WT>
544
+ void graph_weighted_test (const size_t v, const size_t e) {
545
+ for (size_t dir = 0 ; dir <= 1 ; dir++) {
546
+ WeightedAdjMatrix<T, WT> G (dir);
547
+ G.random_graph (v, e, 1 - e, e);
548
+ G.graphviz ();
549
+ std::cout << std::endl;
550
+ Matrix<Weight<int >> M (v, v);
551
+ G.to_matrix (M);
552
+ std::cout << M;
553
+ std::cout << std::endl;
554
+ }
555
+ }
556
+
395
557
int main (int argc, char *argv[]) {
396
558
const size_t v = get_argv (argc, argv, 1 , 5 );
397
559
const size_t e = get_argv (argc, argv, 2 , 10 );
560
+ std::cout << " GraphAdjList" << std::endl;
398
561
graph_test<GraphAdjList<size_t >>(v, e);
562
+ std::cout << " GraphAdjMatrix" << std::endl;
399
563
graph_test<GraphAdjMatrix<size_t >>(v, e);
564
+ std::cout << " WeightedAdjMatrix" << std::endl;
565
+ graph_weighted_test<size_t , int >(v, e);
400
566
return 0 ;
401
567
}
402
568
#endif
0 commit comments