| 1 | //======================================================================= | 
|---|
| 2 | // Copyright 1997, 1998, 1999, 2000 University of Notre Dame. | 
|---|
| 3 | // Authors: Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee | 
|---|
| 4 | // | 
|---|
| 5 | // Distributed under the Boost Software License, Version 1.0. (See | 
|---|
| 6 | // accompanying file LICENSE_1_0.txt or copy at | 
|---|
| 7 | // http://www.boost.org/LICENSE_1_0.txt) | 
|---|
| 8 | //======================================================================= | 
|---|
| 9 |  | 
|---|
| 10 | /* | 
|---|
| 11 |   Reads maximal flow problem in extended DIMACS format. | 
|---|
| 12 |    | 
|---|
| 13 |   Reads from stdin.  | 
|---|
| 14 |  | 
|---|
| 15 |   This works, but could use some polishing.  | 
|---|
| 16 | */ | 
|---|
| 17 |  | 
|---|
| 18 | /* ----------------------------------------------------------------- */ | 
|---|
| 19 |  | 
|---|
| 20 | #include <vector> | 
|---|
| 21 | #include <stdio.h> | 
|---|
| 22 |  | 
|---|
| 23 | namespace boost { | 
|---|
| 24 |  | 
|---|
| 25 | template <class Graph, class CapacityMap, class ReverseEdgeMap> | 
|---|
| 26 | int read_dimacs_max_flow(Graph& g, | 
|---|
| 27 |                          CapacityMap capacity,  | 
|---|
| 28 |                          ReverseEdgeMap reverse_edge, | 
|---|
| 29 |                          typename graph_traits<Graph>::vertex_descriptor& src, | 
|---|
| 30 |                          typename graph_traits<Graph>::vertex_descriptor& sink) | 
|---|
| 31 | { | 
|---|
| 32 |   //  const int MAXLINE = 100;      /* max line length in the input file */ | 
|---|
| 33 |   const int ARC_FIELDS = 3;     /* no of fields in arc line  */ | 
|---|
| 34 |   const int NODE_FIELDS = 2;    /* no of fields in node line  */ | 
|---|
| 35 |   const int P_FIELDS = 3;       /* no of fields in problem line */ | 
|---|
| 36 |   const char* PROBLEM_TYPE = "max"; /* name of problem type*/ | 
|---|
| 37 |  | 
|---|
| 38 |   typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type; | 
|---|
| 39 |   typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor; | 
|---|
| 40 |   typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor; | 
|---|
| 41 |    | 
|---|
| 42 |   std::vector<vertex_descriptor> verts; | 
|---|
| 43 |  | 
|---|
| 44 |   long m, n,                    /*  number of edges and nodes */ | 
|---|
| 45 |     i, head, tail, cap; | 
|---|
| 46 |  | 
|---|
| 47 |   long no_lines=0,              /* no of current input line */ | 
|---|
| 48 |     no_plines=0,                /* no of problem-lines */ | 
|---|
| 49 |     no_nslines=0,               /* no of node-source-lines */ | 
|---|
| 50 |     no_nklines=0,               /* no of node-source-lines */ | 
|---|
| 51 |     no_alines=0;                /* no of arc-lines */ | 
|---|
| 52 |    | 
|---|
| 53 |   std::string in_line;          /* for reading input line */ | 
|---|
| 54 |   char pr_type[3];              /* for reading type of the problem */ | 
|---|
| 55 |   char nd;                      /* source (s) or sink (t) */ | 
|---|
| 56 |    | 
|---|
| 57 |   int k,                        /* temporary */ | 
|---|
| 58 |     err_no;                     /* no of detected error */ | 
|---|
| 59 |  | 
|---|
| 60 |   /* -------------- error numbers & error messages ---------------- */ | 
|---|
| 61 |   const int EN1   = 0; | 
|---|
| 62 |   const int EN2   = 1; | 
|---|
| 63 |   const int EN3   = 2; | 
|---|
| 64 |   const int EN4   = 3; | 
|---|
| 65 |   //  const int EN6   = 4; | 
|---|
| 66 |   //  const int EN10  = 5; | 
|---|
| 67 |   //  const int EN7   = 6; | 
|---|
| 68 |   const int EN8   = 7; | 
|---|
| 69 |   const int EN9   = 8; | 
|---|
| 70 |   const int EN11  = 9; | 
|---|
| 71 |   const int EN12 = 10; | 
|---|
| 72 |   //  const int EN13 = 11; | 
|---|
| 73 |   const int EN14 = 12; | 
|---|
| 74 |   const int EN16 = 13; | 
|---|
| 75 |   const int EN15 = 14; | 
|---|
| 76 |   const int EN17 = 15; | 
|---|
| 77 |   const int EN18 = 16; | 
|---|
| 78 |   const int EN21 = 17; | 
|---|
| 79 |   const int EN19 = 18; | 
|---|
| 80 |   const int EN20 = 19; | 
|---|
| 81 |   const int EN22 = 20; | 
|---|
| 82 |    | 
|---|
| 83 |   static char *err_message[] =  | 
|---|
| 84 |   {  | 
|---|
| 85 |     /* 0*/    "more than one problem line.", | 
|---|
| 86 |     /* 1*/    "wrong number of parameters in the problem line.", | 
|---|
| 87 |     /* 2*/    "it is not a Max Flow problem line.", | 
|---|
| 88 |     /* 3*/    "bad value of a parameter in the problem line.", | 
|---|
| 89 |     /* 4*/    "can't obtain enough memory to solve this problem.", | 
|---|
| 90 |     /* 5*/    "more than one line with the problem name.", | 
|---|
| 91 |     /* 6*/    "can't read problem name.", | 
|---|
| 92 |     /* 7*/    "problem description must be before node description.", | 
|---|
| 93 |     /* 8*/    "this parser doesn't support multiply sources and sinks.", | 
|---|
| 94 |     /* 9*/    "wrong number of parameters in the node line.", | 
|---|
| 95 |     /*10*/    "wrong value of parameters in the node line.", | 
|---|
| 96 |     /*11*/    " ", | 
|---|
| 97 |     /*12*/    "source and sink descriptions must be before arc descriptions.", | 
|---|
| 98 |     /*13*/    "too many arcs in the input.", | 
|---|
| 99 |     /*14*/    "wrong number of parameters in the arc line.", | 
|---|
| 100 |     /*15*/    "wrong value of parameters in the arc line.", | 
|---|
| 101 |     /*16*/    "unknown line type in the input.", | 
|---|
| 102 |     /*17*/    "reading error.", | 
|---|
| 103 |     /*18*/    "not enough arcs in the input.", | 
|---|
| 104 |     /*19*/    "source or sink doesn't have incident arcs.", | 
|---|
| 105 |     /*20*/    "can't read anything from the input file." | 
|---|
| 106 |   }; | 
|---|
| 107 |   /* --------------------------------------------------------------- */ | 
|---|
| 108 |  | 
|---|
| 109 |   /* The main loop: | 
|---|
| 110 |      -  reads the line of the input, | 
|---|
| 111 |      -  analyses its type, | 
|---|
| 112 |      -  checks correctness of parameters, | 
|---|
| 113 |      -  puts data to the arrays, | 
|---|
| 114 |      -  does service functions | 
|---|
| 115 |   */ | 
|---|
| 116 |  | 
|---|
| 117 |   while (std::getline(std::cin, in_line)) { | 
|---|
| 118 |     ++no_lines; | 
|---|
| 119 |  | 
|---|
| 120 |     switch (in_line[0]) { | 
|---|
| 121 |     case 'c':                  /* skip lines with comments */ | 
|---|
| 122 |     case '\n':                 /* skip empty lines   */ | 
|---|
| 123 |     case '\0':                 /* skip empty lines at the end of file */ | 
|---|
| 124 |       break; | 
|---|
| 125 |        | 
|---|
| 126 |     case 'p':                  /* problem description      */ | 
|---|
| 127 |       if ( no_plines > 0 ) | 
|---|
| 128 |         /* more than one problem line */ | 
|---|
| 129 |         { err_no = EN1 ; goto error; } | 
|---|
| 130 |        | 
|---|
| 131 |       no_plines = 1; | 
|---|
| 132 |        | 
|---|
| 133 |       if ( | 
|---|
| 134 |           /* reading problem line: type of problem, no of nodes, no of arcs */ | 
|---|
| 135 |           sscanf ( in_line.c_str(), "%*c %3s %ld %ld", pr_type, &n, &m ) | 
|---|
| 136 |           != P_FIELDS | 
|---|
| 137 |           ) | 
|---|
| 138 |         /*wrong number of parameters in the problem line*/ | 
|---|
| 139 |         { err_no = EN2; goto error; } | 
|---|
| 140 |        | 
|---|
| 141 |       if ( strcmp ( pr_type, PROBLEM_TYPE ) ) | 
|---|
| 142 |         /*wrong problem type*/ | 
|---|
| 143 |         { err_no = EN3; goto error; } | 
|---|
| 144 |        | 
|---|
| 145 |       if ( n <= 0  || m <= 0 ) | 
|---|
| 146 |         /*wrong value of no of arcs or nodes*/ | 
|---|
| 147 |         { err_no = EN4; goto error; } | 
|---|
| 148 |  | 
|---|
| 149 |       { | 
|---|
| 150 |         for (long vi = 0; vi < n; ++vi) | 
|---|
| 151 |           verts.push_back(add_vertex(g)); | 
|---|
| 152 |       } | 
|---|
| 153 |       break; | 
|---|
| 154 |        | 
|---|
| 155 |     case 'n':                    /* source(s) description */ | 
|---|
| 156 |       if ( no_plines == 0 ) | 
|---|
| 157 |         /* there was not problem line above */ | 
|---|
| 158 |         { err_no = EN8; goto error; } | 
|---|
| 159 |        | 
|---|
| 160 |       /* reading source  or sink */ | 
|---|
| 161 |       k = sscanf ( in_line.c_str(),"%*c %ld %c", &i, &nd ); | 
|---|
| 162 |       --i; // index from 0 | 
|---|
| 163 |       if ( k < NODE_FIELDS ) | 
|---|
| 164 |         /* node line is incorrect */ | 
|---|
| 165 |         { err_no = EN11; goto error; } | 
|---|
| 166 |        | 
|---|
| 167 |       if ( i < 0 || i > n ) | 
|---|
| 168 |         /* wrong value of node */ | 
|---|
| 169 |         { err_no = EN12; goto error; } | 
|---|
| 170 |        | 
|---|
| 171 |       switch (nd) { | 
|---|
| 172 |       case 's':  /* source line */ | 
|---|
| 173 |          | 
|---|
| 174 |         if ( no_nslines != 0) | 
|---|
| 175 |           /* more than one source line */  | 
|---|
| 176 |           { err_no = EN9; goto error; } | 
|---|
| 177 |          | 
|---|
| 178 |         no_nslines = 1; | 
|---|
| 179 |         src = verts[i]; | 
|---|
| 180 |         break; | 
|---|
| 181 |          | 
|---|
| 182 |       case 't':  /* sink line */ | 
|---|
| 183 |          | 
|---|
| 184 |         if ( no_nklines != 0) | 
|---|
| 185 |           /* more than one sink line */ | 
|---|
| 186 |           { err_no = EN9; goto error; } | 
|---|
| 187 |          | 
|---|
| 188 |         no_nklines = 1; | 
|---|
| 189 |         sink = verts[i]; | 
|---|
| 190 |         break; | 
|---|
| 191 |          | 
|---|
| 192 |       default: | 
|---|
| 193 |         /* wrong type of node-line */ | 
|---|
| 194 |         err_no = EN12; goto error;  | 
|---|
| 195 |       } | 
|---|
| 196 |       break; | 
|---|
| 197 |        | 
|---|
| 198 |     case 'a':                    /* arc description */ | 
|---|
| 199 |       if ( no_nslines == 0 || no_nklines == 0 )  | 
|---|
| 200 |         /* there was not source and sink description above */ | 
|---|
| 201 |         { err_no = EN14; goto error; } | 
|---|
| 202 |        | 
|---|
| 203 |       if ( no_alines >= m ) | 
|---|
| 204 |         /*too many arcs on input*/ | 
|---|
| 205 |         { err_no = EN16; goto error; } | 
|---|
| 206 |        | 
|---|
| 207 |       if ( | 
|---|
| 208 |           /* reading an arc description */ | 
|---|
| 209 |           sscanf ( in_line.c_str(),"%*c %ld %ld %ld", | 
|---|
| 210 |                    &tail, &head, &cap ) | 
|---|
| 211 |           != ARC_FIELDS | 
|---|
| 212 |           )  | 
|---|
| 213 |         /* arc description is not correct */ | 
|---|
| 214 |         { err_no = EN15; goto error; } | 
|---|
| 215 |  | 
|---|
| 216 |       --tail; // index from 0, not 1 | 
|---|
| 217 |       --head; | 
|---|
| 218 |       if ( tail < 0  ||  tail > n  || | 
|---|
| 219 |            head < 0  ||  head > n   | 
|---|
| 220 |            ) | 
|---|
| 221 |         /* wrong value of nodes */ | 
|---|
| 222 |         { err_no = EN17; goto error; } | 
|---|
| 223 |  | 
|---|
| 224 |       {       | 
|---|
| 225 |         edge_descriptor e1, e2;  | 
|---|
| 226 |         bool in1, in2; | 
|---|
| 227 |         tie(e1, in1) = add_edge(verts[tail], verts[head], g); | 
|---|
| 228 |         tie(e2, in2) = add_edge(verts[head], verts[tail], g); | 
|---|
| 229 |         if (!in1 || !in2) { | 
|---|
| 230 |           std::cerr << "unable to add edge (" << head << "," << tail << ")"  | 
|---|
| 231 |                     << std::endl; | 
|---|
| 232 |           return -1; | 
|---|
| 233 |         } | 
|---|
| 234 |         capacity[e1] = cap; | 
|---|
| 235 |         capacity[e2] = 0; | 
|---|
| 236 |         reverse_edge[e1] = e2; | 
|---|
| 237 |         reverse_edge[e2] = e1; | 
|---|
| 238 |       } | 
|---|
| 239 |       ++no_alines; | 
|---|
| 240 |       break; | 
|---|
| 241 |        | 
|---|
| 242 |     default: | 
|---|
| 243 |       /* unknown type of line */ | 
|---|
| 244 |       err_no = EN18; goto error; | 
|---|
| 245 |        | 
|---|
| 246 |     } /* end of switch */ | 
|---|
| 247 |   }     /* end of input loop */ | 
|---|
| 248 |    | 
|---|
| 249 |   /* ----- all is red  or  error while reading ----- */  | 
|---|
| 250 |    | 
|---|
| 251 |   if ( feof (stdin) == 0 ) /* reading error */ | 
|---|
| 252 |     { err_no=EN21; goto error; }  | 
|---|
| 253 |    | 
|---|
| 254 |   if ( no_lines == 0 ) /* empty input */ | 
|---|
| 255 |     { err_no = EN22; goto error; }  | 
|---|
| 256 |    | 
|---|
| 257 |   if ( no_alines < m ) /* not enough arcs */ | 
|---|
| 258 |     { err_no = EN19; goto error; }  | 
|---|
| 259 |    | 
|---|
| 260 |   if ( out_degree(src, g) == 0 || out_degree(sink, g) == 0  )  | 
|---|
| 261 |     /* no arc goes out of the source */ | 
|---|
| 262 |     { err_no = EN20; goto error; } | 
|---|
| 263 |    | 
|---|
| 264 |   /* Thanks God! all is done */ | 
|---|
| 265 |   return (0); | 
|---|
| 266 |    | 
|---|
| 267 |   /* ---------------------------------- */ | 
|---|
| 268 |  error:  /* error found reading input */ | 
|---|
| 269 |    | 
|---|
| 270 |   printf ( "\nline %ld of input - %s\n",  | 
|---|
| 271 |            no_lines, err_message[err_no] ); | 
|---|
| 272 |    | 
|---|
| 273 |   exit (1); | 
|---|
| 274 |   return (0); /* to avoid warning */ | 
|---|
| 275 | } | 
|---|
| 276 | /* --------------------   end of parser  -------------------*/ | 
|---|
| 277 |  | 
|---|
| 278 | } // namespace boost | 
|---|