decontamination.cpp (4398B)
1 /* decontamination.cpp -- find decontamination sequence of input graph 2 * Antoine Amarilli, 2015 3 * see http://cstheory.stackexchange.com/q/30592/4795 for problem statement 4 * 5 * To use, set MAXN in the code to be more than the number of vertices to 6 * consider, and compile with g++ -Wall -O3 -std=c++11 7 * 8 * Provide graph in stdin with each edge represented by the source and target 9 * represented as integers, separated by a space, edges separated by newline. 10 * EOF terminates. Vertices should be numbered from 0 to n-1. 11 * 12 * Output is a decontamination sequence with minimal number of nodes to be 13 * simultaneously decontaminated, then minimal order, then (normally) minimum in 14 * lexicographic order, represented as a bit vector of the node contaminations 15 * separated by the nodes to query. */ 16 17 // max number of vertices, change this 18 #define MAXN 5 19 20 // if set, only display the graph, not the strategy 21 #define DISPLAYGRAPH 0 22 23 // if set, symmetrize graph 24 #define UNDIRECTED 1 25 26 // maximal number of nodes to shoot simultaneously 27 #define MAXK 1 28 29 #include <cstdio> 30 #include <iostream> 31 #include <assert.h> 32 #include <queue> 33 #include <bitset> 34 #include <algorithm> 35 #include <unordered_map> 36 37 #define max(a, b) ((b)>(a) ? (b) : (a)) 38 39 using namespace std; 40 41 int main() { 42 // n_vertices, n_edges 43 int n = 0; 44 // adjacency lists 45 int G[MAXN][MAXN]; 46 // degrees 47 int nG[MAXN]; 48 bool found_solution = false; 49 50 for (int i = 0; i < MAXN; i++) 51 nG[i] = 0; 52 while (true) { 53 int f, t, ret; 54 ret = scanf("%d %d\n", &f, &t); 55 if (ret != 2) 56 break; 57 // vertices should be numbered from 0 to n-1 with n <= MAXN 58 assert(0 <= f && f < MAXN && 0 <= t && t < MAXN); 59 n = max(n, max(f, t)); 60 G[f][nG[f]] = t; 61 nG[f]++; 62 if (UNDIRECTED) { 63 G[t][nG[t]] = f; 64 nG[t]++; 65 } 66 } 67 n++; // so that vertices are from 0 to n-1 68 69 for (int k = 1; k <= MAXK; k++) { 70 // decontaminate simultaneously k nodes 71 // do a BFS on configurations 72 73 // queue of configurations to consider 74 queue<bitset<MAXN> > q; 75 // predecessor configuration of each reachable configuration 76 unordered_map<bitset<MAXN>, bitset<MAXN> > p; 77 // action to reach each reachable configuration from predecessor 78 unordered_map<bitset<MAXN>, string > a; 79 80 // start configuration 81 bitset<MAXN> s; 82 for (int i = 0; i < n; i++) 83 s.set(i); 84 q.push(s); 85 86 while (!q.empty()) { 87 bitset<MAXN> c = q.front(); 88 if (!c.count()) 89 break; // target configuration reached 90 q.pop(); 91 // http://rosettacode.org/wiki/Combinations#C.2B.2B 92 string bm(k, 1); 93 bm.resize(n, 0); 94 do { 95 bitset<MAXN> nc; // new possible configuration 96 int myidx = -1; 97 for (int i = 0; i < n; i++) 98 if (bm[i]) 99 myidx = i; 100 for (int i = 0; i < n; i++) 101 if (c[i] && !bm[i]) 102 // i is contaminated and was not decontaminated at this turn 103 for (int j = 0; j < nG[i]; j++) 104 // all possible contaminations by i 105 nc.set(G[i][j]); 106 if (DISPLAYGRAPH) 107 cout << c << " -> " << nc << " [label='" << myidx << "'];" << endl; 108 //cout << nc << endl; 109 if (!p.count(nc)) { 110 // nc was not reachable yet 111 p[nc] = c; 112 a[nc] = bm; 113 q.push(nc); 114 } 115 } while (prev_permutation(bm.begin(), bm.end())); 116 } 117 118 if (DISPLAYGRAPH) 119 return 0; 120 121 bitset<MAXN> e; 122 if (p.count(e)) { 123 // target configuration was reached: all nodes decontaminated 124 // read back the path to the target configuration 125 vector<string> v; 126 do { 127 v.push_back(e.to_string()); 128 v.push_back(a[e]); 129 e = p[e]; 130 } while (p.count(e) && p[e] != e); 131 v.push_back(e.to_string()); 132 // path is in reverse order 133 reverse(v.begin(), v.end()); 134 for (unsigned int i = 0; i < v.size(); i++) { 135 if (i % 2 == 1) { 136 // display decontamination action 137 for (int j = 0; j < n; j++) { 138 if (v[i][j]) 139 printf("%d ", j); 140 } 141 } else { 142 // display configuration 143 cout << v[i]; 144 } 145 printf("\n"); 146 } 147 found_solution = true; 148 break; 149 } 150 // if target configuration was not reached, increase k 151 } 152 153 if (!found_solution) 154 printf("no solution found\n"); 155 156 return 0; 157 } 158