回答編集履歴
6
コード整理
    
        answer	
    CHANGED
    
    | @@ -22,8 +22,9 @@ | |
| 22 22 | 
             
            #include <stdio.h>
         | 
| 23 23 | 
             
            #include <stdlib.h>
         | 
| 24 24 | 
             
            #include <string.h>
         | 
| 25 | 
            +
            #include <assert.h>
         | 
| 25 26 |  | 
| 26 | 
            -
            //#define  | 
| 27 | 
            +
            //#define CHECK_TEST
         | 
| 27 28 | 
             
            #define CHECK_LOG
         | 
| 28 29 |  | 
| 29 30 | 
             
            typedef struct {
         | 
| @@ -32,143 +33,129 @@ | |
| 32 33 | 
             
              double dist; //点間の距離
         | 
| 33 34 | 
             
            } Adjacent;
         | 
| 34 35 |  | 
| 36 | 
            +
            int isConnected(Adjacent *a, int p) {
         | 
| 37 | 
            +
              return p == a->u || p == a->v;
         | 
| 38 | 
            +
            }
         | 
| 39 | 
            +
            int otherPoint(Adjacent *a, int p) {
         | 
| 40 | 
            +
              return p == a->u ? a->v : a->u;
         | 
| 41 | 
            +
            }
         | 
| 42 | 
            +
             | 
| 35 43 | 
             
            typedef struct {
         | 
| 36 44 | 
             
              int p, c;
         | 
| 37 45 | 
             
            } PC;
         | 
| 38 46 |  | 
| 47 | 
            +
            void setPc(PC *pc, int i, int p, int c) {
         | 
| 48 | 
            +
              pc[i].p = p;
         | 
| 49 | 
            +
              pc[i].c = c;
         | 
| 50 | 
            +
            }
         | 
| 51 | 
            +
            int countAndCrossCheck(PC *pc) {
         | 
| 52 | 
            +
              return ++pc->c > 2;
         | 
| 53 | 
            +
            }
         | 
| 54 | 
            +
             | 
| 55 | 
            +
            //size バイトのメモリを確保し、各バイトに value をセット
         | 
| 56 | 
            +
            void *allocAndClear(size_t size, int value) {
         | 
| 57 | 
            +
              return memset(malloc(size), value, size);
         | 
| 58 | 
            +
            }
         | 
| 59 | 
            +
             | 
| 39 60 | 
             
            //判定
         | 
| 40 61 | 
             
            #define DISCARD (-1) //(最期に追加した辺を)破棄
         | 
| 41 62 | 
             
            #define CONTINUE (0) //継続
         | 
| 42 63 | 
             
            #define COMPLETE (1) //完了
         | 
| 43 64 |  | 
| 44 | 
            -
            int check(int n, int c, Adjacent ** | 
| 65 | 
            +
            int check(int n, int c, Adjacent **roads) {
         | 
| 45 66 | 
             
            #ifdef CHECK_LOG
         | 
| 46 67 | 
             
              printf("n=%d,c=%d\n", n, c);
         | 
| 47 | 
            -
              for(int i=0; i<c; i++) printf("%d-%d\n",  | 
| 68 | 
            +
              for(int i=0; i<c; i++) printf("%d-%d\n", roads[i]->u, roads[i]->v);
         | 
| 48 69 | 
             
            #endif //CHECK_LOG
         | 
| 49 70 |  | 
| 50 71 | 
             
              if(c > n) return DISCARD; //辺が多くなったなら破棄
         | 
| 51 72 |  | 
| 52 | 
            -
              int  | 
| 73 | 
            +
              int hasCross = 0; //false
         | 
| 53 74 | 
             
              int hasClosed = 0; //false
         | 
| 54 75 |  | 
| 55 | 
            -
              //最期の辺( | 
| 76 | 
            +
              //最期の辺(roads[c-1])の接続先を追う
         | 
| 56 | 
            -
               | 
| 77 | 
            +
              int *used = allocAndClear(sizeof(int) * (c-1), 0); //roads に index で対応するフラグ
         | 
| 57 | 
            -
              PC *q =  | 
| 78 | 
            +
              PC *q = allocAndClear(sizeof(PC) * n, 0); //点の探索キュー&探索履歴・接続カウント
         | 
| 58 79 |  | 
| 59 80 | 
             
              int wi = 0, ri = 0;
         | 
| 60 | 
            -
              q | 
| 81 | 
            +
              setPc(q, wi++, roads[c-1]->u, 1); //最後に追加した辺の両端を追加
         | 
| 61 | 
            -
              q[wi++].c = 1;
         | 
| 62 | 
            -
              q | 
| 82 | 
            +
              setPc(q, wi++, roads[c-1]->v, 1);
         | 
| 63 | 
            -
              q[wi++].c = 1;
         | 
| 64 | 
            -
              cpy[c-1] = NULL;
         | 
| 65 83 | 
             
              while(ri < wi) {
         | 
| 66 84 | 
             
                PC *pc = &q[ri++];
         | 
| 67 | 
            -
                for(int i=0; i<c-1; i++) { //点  | 
| 85 | 
            +
                for(int i=0; i<c-1; i++) { //点 pc に繋がっている未使用辺を探し、 pc の逆側の点を (q に無ければ )q に追加
         | 
| 68 | 
            -
                  if( | 
| 86 | 
            +
                  if(used[i] || !isConnected(roads[i], pc->p)) continue;
         | 
| 69 | 
            -
                  if(++pc->c > 2) rinf = DISCARD;
         | 
| 70 87 |  | 
| 88 | 
            +
                  used[i] = 1; //true
         | 
| 89 | 
            +
                  hasCross |= countAndCrossCheck(pc);
         | 
| 71 | 
            -
                  int np =  | 
| 90 | 
            +
                  int np = otherPoint(roads[i], pc->p); //p の逆側の点
         | 
| 72 | 
            -
                  cpy[i] = NULL;
         | 
| 73 91 |  | 
| 74 92 | 
             
                  int found = 0; //false
         | 
| 75 | 
            -
                  for(int j=0; j<wi; j++) { | 
| 93 | 
            +
                  for(int j=0; j<wi; j++) {
         | 
| 76 | 
            -
                    if(q[j].p == np) {
         | 
| 77 | 
            -
             | 
| 94 | 
            +
                    if(q[j].p == np) { //探索済みor探索予定の点に繋がる?
         | 
| 78 95 | 
             
                      found = 1; //true
         | 
| 79 | 
            -
                       | 
| 96 | 
            +
                      hasCross |= countAndCrossCheck(&q[j]);
         | 
| 80 97 | 
             
                    }
         | 
| 81 98 | 
             
                  }
         | 
| 82 | 
            -
                  if(!found) {
         | 
| 83 | 
            -
             | 
| 99 | 
            +
                  hasClosed |= found;
         | 
| 84 | 
            -
             | 
| 100 | 
            +
                  if(!found) setPc(q, wi++, np, 1);
         | 
| 85 | 
            -
                  }
         | 
| 86 101 | 
             
                }
         | 
| 87 102 | 
             
              }
         | 
| 88 103 |  | 
| 89 104 | 
             
            #ifdef CHECK_LOG
         | 
| 90 105 | 
             
              printf("wi=%d\n", wi);
         | 
| 91 106 | 
             
              for(int i=0; i<wi; i++) printf("p=%d,c=%d\n", q[i].p, q[i].c);
         | 
| 107 | 
            +
              printf("hasCross=%d, hasClosed=%d\n", hasCross, hasClosed);
         | 
| 108 | 
            +
              printf("\n");
         | 
| 92 109 | 
             
            #endif //CHECK_LOG
         | 
| 93 110 |  | 
| 94 | 
            -
              if(hasClosed) {
         | 
| 95 | 
            -
                rinf = DISCARD;
         | 
| 96 | 
            -
                if(wi == n) {
         | 
| 97 | 
            -
                  int count = 0;
         | 
| 98 | 
            -
                  for(int i=0; i<wi; i++) if(q[i].c == 2) count ++;
         | 
| 99 | 
            -
                  if(count == n) rinf = COMPLETE; //点全部が 2 辺と接続した閉路なら COMPLETE
         | 
| 100 | 
            -
                }
         | 
| 101 | 
            -
              }
         | 
| 102 | 
            -
             | 
| 103 | 
            -
              free( | 
| 111 | 
            +
              free(used);
         | 
| 104 112 | 
             
              free(q);
         | 
| 105 113 |  | 
| 106 | 
            -
             | 
| 114 | 
            +
              if(hasCross || (hasClosed && c < n)) return DISCARD;
         | 
| 107 | 
            -
               | 
| 115 | 
            +
              if(hasClosed && c == n) return COMPLETE;
         | 
| 108 | 
            -
            #endif //CHECK_LOG
         | 
| 109 | 
            -
              return  | 
| 116 | 
            +
              return CONTINUE;
         | 
| 110 117 | 
             
            }
         | 
| 111 118 |  | 
| 112 119 | 
             
            //greedy法
         | 
| 113 | 
            -
             | 
| 120 | 
            +
            Adjacent **greedy(int n, int m, Adjacent *adjacent) {
         | 
| 121 | 
            +
              Adjacent **result = malloc(sizeof(Adjacent*) * n);
         | 
| 114 122 | 
             
              for(int i=0, c=0; i<m; i++) {
         | 
| 115 123 | 
             
                result[c++] = &adjacent[i];
         | 
| 116 124 | 
             
                switch(check(n, c, result)) {
         | 
| 117 | 
            -
                case COMPLETE: return  | 
| 125 | 
            +
                case COMPLETE: return result;
         | 
| 118 126 | 
             
                case DISCARD: c--;
         | 
| 119 127 | 
             
                }
         | 
| 120 128 | 
             
              }
         | 
| 129 | 
            +
              free(result);
         | 
| 121 | 
            -
              return  | 
| 130 | 
            +
              return NULL;
         | 
| 122 131 | 
             
            }
         | 
| 123 132 |  | 
| 124 133 | 
             
            //表示
         | 
| 125 | 
            -
            void print(int  | 
| 134 | 
            +
            void print(int n, Adjacent **result) {
         | 
| 126 135 | 
             
              printf("Final Path: ");
         | 
| 127 136 | 
             
              double total = 0;
         | 
| 128 137 | 
             
              int i = 0;
         | 
| 129 138 | 
             
              int p = result[i]->u;
         | 
| 130 139 | 
             
              printf("%d", p);
         | 
| 131 | 
            -
              for(int j=0, k; j< | 
| 140 | 
            +
              for(int j=0, k; j<n; j++) {
         | 
| 132 | 
            -
                p =  | 
| 141 | 
            +
                p = otherPoint(result[i], p);
         | 
| 133 142 | 
             
                printf(" -> %d", p);
         | 
| 134 143 | 
             
                total += result[i]->dist;
         | 
| 135 | 
            -
                for(k=i, i=0; i==k || (result[i] | 
| 144 | 
            +
                for(k=i, i=0; i==k || !isConnected(result[i], p); i++); //次の i
         | 
| 136 145 | 
             
              }
         | 
| 137 146 | 
             
              printf("\n");
         | 
| 138 147 | 
             
              printf("Total Distance: %.1lf\n", total);
         | 
| 139 148 | 
             
            }
         | 
| 140 149 |  | 
| 141 150 | 
             
            int main(void) {
         | 
| 142 | 
            -
            #ifdef  | 
| 151 | 
            +
            #ifdef CHECK_TEST
         | 
| 143 | 
            -
              printf("TEST start\n");
         | 
| 144 | 
            -
              Adjacent testdata1[] = {
         | 
| 152 | 
            +
              Adjacent testdata1[] = { {0,1,100}, {2,3,110}, {3,4,120}, {2,4,130} };
         | 
| 145 | 
            -
                  {0,1,100},
         | 
| 146 | 
            -
                  {2,3,110},
         | 
| 147 | 
            -
                  {3,4,120},
         | 
| 148 | 
            -
                  {2,4,130},
         | 
| 149 | 
            -
              };
         | 
| 150 | 
            -
              Adjacent *test1[] = {
         | 
| 153 | 
            +
              Adjacent *test1[] = { &testdata1[0], &testdata1[1], &testdata1[2], &testdata1[3] };
         | 
| 151 | 
            -
                  &testdata1[0],
         | 
| 152 | 
            -
                  &testdata1[1],
         | 
| 153 | 
            -
                  &testdata1[2],
         | 
| 154 | 
            -
                  &testdata1[3],
         | 
| 155 | 
            -
              };
         | 
| 156 | 
            -
               | 
| 154 | 
            +
              assert(check(5, 4, test1) == DISCARD);
         | 
| 157 155 |  | 
| 158 | 
            -
              Adjacent testdata2[4] = {
         | 
| 156 | 
            +
              Adjacent testdata2[4] = { {0,2,100}, {2,3,110}, {3,4,120}, {1,4,130} };
         | 
| 159 | 
            -
                  {0,2,100},
         | 
| 160 | 
            -
                  {2,3,110},
         | 
| 161 | 
            -
                  {3,4,120},
         | 
| 162 | 
            -
                  {1,4,130},
         | 
| 163 | 
            -
              };
         | 
| 164 | 
            -
              Adjacent *test2[] = {
         | 
| 157 | 
            +
              Adjacent *test2[] = { &testdata2[0], &testdata2[1], &testdata2[2], &testdata2[3] };
         | 
| 165 | 
            -
                  &testdata2[0],
         | 
| 166 | 
            -
                  &testdata2[1],
         | 
| 167 | 
            -
                  &testdata2[2],
         | 
| 168 | 
            -
                  &testdata2[3],
         | 
| 169 | 
            -
              };
         | 
| 170 | 
            -
               | 
| 158 | 
            +
              assert(check(5, 4, test2) == CONTINUE);
         | 
| 171 | 
            -
              printf("end\n");
         | 
| 172 159 | 
             
            #else //TEST
         | 
| 173 160 | 
             
              //ファイル読み込み・ソート等を省略
         | 
| 174 161 | 
             
              int n = 5; //点の数
         | 
| @@ -185,12 +172,11 @@ | |
| 185 172 | 
             
                  {0,4, 1055.9},
         | 
| 186 173 | 
             
                  {2,4, 1592.3},
         | 
| 187 174 | 
             
              };
         | 
| 188 | 
            -
              Adjacent *result[10] = {0}; //結果保存領域(adjacents の要素へのポインタ)
         | 
| 189 175 |  | 
| 190 | 
            -
               | 
| 176 | 
            +
              Adjacent **result = greedy(n, m, adjacents);
         | 
| 191 | 
            -
             | 
| 192 | 
            -
              if( | 
| 177 | 
            +
              if(result) {
         | 
| 193 | 
            -
                print( | 
| 178 | 
            +
                print(n, result); //最終的な経路を表示
         | 
| 179 | 
            +
                free(result);
         | 
| 194 180 | 
             
              } else {
         | 
| 195 181 | 
             
                printf("Failure\n");
         | 
| 196 182 | 
             
              }
         | 
| @@ -204,7 +190,8 @@ | |
| 204 190 | 
             
            wi=2
         | 
| 205 191 | 
             
            p=1,c=1
         | 
| 206 192 | 
             
            p=3,c=1
         | 
| 207 | 
            -
             | 
| 193 | 
            +
            hasCross=0, hasClosed=0
         | 
| 194 | 
            +
             | 
| 208 195 | 
             
            n=5,c=2
         | 
| 209 196 | 
             
            1-3
         | 
| 210 197 | 
             
            0-3
         | 
| @@ -212,7 +199,8 @@ | |
| 212 199 | 
             
            p=0,c=1
         | 
| 213 200 | 
             
            p=3,c=2
         | 
| 214 201 | 
             
            p=1,c=1
         | 
| 215 | 
            -
             | 
| 202 | 
            +
            hasCross=0, hasClosed=0
         | 
| 203 | 
            +
             | 
| 216 204 | 
             
            n=5,c=3
         | 
| 217 205 | 
             
            1-3
         | 
| 218 206 | 
             
            0-3
         | 
| @@ -221,7 +209,8 @@ | |
| 221 209 | 
             
            p=0,c=2
         | 
| 222 210 | 
             
            p=1,c=2
         | 
| 223 211 | 
             
            p=3,c=2
         | 
| 224 | 
            -
             | 
| 212 | 
            +
            hasCross=0, hasClosed=1
         | 
| 213 | 
            +
             | 
| 225 214 | 
             
            n=5,c=3
         | 
| 226 215 | 
             
            1-3
         | 
| 227 216 | 
             
            0-3
         | 
| @@ -231,7 +220,8 @@ | |
| 231 220 | 
             
            p=4,c=1
         | 
| 232 221 | 
             
            p=3,c=2
         | 
| 233 222 | 
             
            p=0,c=1
         | 
| 234 | 
            -
             | 
| 223 | 
            +
            hasCross=0, hasClosed=0
         | 
| 224 | 
            +
             | 
| 235 225 | 
             
            n=5,c=4
         | 
| 236 226 | 
             
            1-3
         | 
| 237 227 | 
             
            0-3
         | 
| @@ -243,7 +233,8 @@ | |
| 243 233 | 
             
            p=3,c=2
         | 
| 244 234 | 
             
            p=1,c=2
         | 
| 245 235 | 
             
            p=4,c=1
         | 
| 246 | 
            -
             | 
| 236 | 
            +
            hasCross=0, hasClosed=0
         | 
| 237 | 
            +
             | 
| 247 238 | 
             
            n=5,c=5
         | 
| 248 239 | 
             
            1-3
         | 
| 249 240 | 
             
            0-3
         | 
| @@ -256,7 +247,8 @@ | |
| 256 247 | 
             
            p=0,c=2
         | 
| 257 248 | 
             
            p=1,c=2
         | 
| 258 249 | 
             
            p=4,c=1
         | 
| 259 | 
            -
             | 
| 250 | 
            +
            hasCross=1, hasClosed=1
         | 
| 251 | 
            +
             | 
| 260 252 | 
             
            n=5,c=5
         | 
| 261 253 | 
             
            1-3
         | 
| 262 254 | 
             
            0-3
         | 
| @@ -269,7 +261,8 @@ | |
| 269 261 | 
             
            p=1,c=2
         | 
| 270 262 | 
             
            p=0,c=2
         | 
| 271 263 | 
             
            p=2,c=1
         | 
| 272 | 
            -
             | 
| 264 | 
            +
            hasCross=1, hasClosed=1
         | 
| 265 | 
            +
             | 
| 273 266 | 
             
            n=5,c=5
         | 
| 274 267 | 
             
            1-3
         | 
| 275 268 | 
             
            0-3
         | 
| @@ -282,7 +275,8 @@ | |
| 282 275 | 
             
            p=3,c=2
         | 
| 283 276 | 
             
            p=4,c=1
         | 
| 284 277 | 
             
            p=0,c=2
         | 
| 285 | 
            -
             | 
| 278 | 
            +
            hasCross=1, hasClosed=1
         | 
| 279 | 
            +
             | 
| 286 280 | 
             
            n=5,c=5
         | 
| 287 281 | 
             
            1-3
         | 
| 288 282 | 
             
            0-3
         | 
| @@ -295,7 +289,8 @@ | |
| 295 289 | 
             
            p=3,c=2
         | 
| 296 290 | 
             
            p=2,c=1
         | 
| 297 291 | 
             
            p=1,c=2
         | 
| 298 | 
            -
             | 
| 292 | 
            +
            hasCross=1, hasClosed=1
         | 
| 293 | 
            +
             | 
| 299 294 | 
             
            n=5,c=5
         | 
| 300 295 | 
             
            1-3
         | 
| 301 296 | 
             
            0-3
         | 
| @@ -308,7 +303,8 @@ | |
| 308 303 | 
             
            p=0,c=2
         | 
| 309 304 | 
             
            p=1,c=2
         | 
| 310 305 | 
             
            p=3,c=2
         | 
| 311 | 
            -
             | 
| 306 | 
            +
            hasCross=0, hasClosed=1
         | 
| 307 | 
            +
             | 
| 312 308 | 
             
            Final Path: 1 -> 3 -> 0 -> 2 -> 4 -> 1
         | 
| 313 309 | 
             
            Total Distance: 3311.1
         | 
| 314 310 | 
             
            ```
         | 
5
コード修正
    
        answer	
    CHANGED
    
    | @@ -1,44 +1,112 @@ | |
| 1 1 | 
             
            valid 関数は、最後に追加した辺を用いるかどうかを返します。
         | 
| 2 | 
            -
            最後に追加した辺を用いるかどうかは、以下の点で判断出来ます。
         | 
| 2 | 
            +
            ~~最後に追加した辺を用いるかどうかは、以下の点で判断出来ます。~~
         | 
| 3 3 |  | 
| 4 | 
            -
            1. 辺の数が全ての点を回るのに不足している場合:閉路が出来たら false, 出来なかったなら true
         | 
| 4 | 
            +
            ~~1. 辺の数が全ての点を回るのに不足している場合:閉路が出来たら false, 出来なかったなら true
         | 
| 5 5 | 
             
            2. 辺の数が全ての点を回るのに必要な数に達した場合:完全な閉路が出来たら true, 出来なかったら false
         | 
| 6 | 
            -
            3. 辺の数が多くなった場合:false
         | 
| 6 | 
            +
            3. 辺の数が多くなった場合:false~~
         | 
| 7 7 |  | 
| 8 | 
            -
            1 と 2 で閉路の扱いが逆ですので、判断もそのようにする必要があると思います。
         | 
| 8 | 
            +
            ~~1 と 2 で閉路の扱いが逆ですので、判断もそのようにする必要があると思います。~~
         | 
| 9 9 |  | 
| 10 | 
            -
            閉路の判定は、(実際に辿ってみなくても)各点から出る辺の数によって判断出来るのではないでしょうか。
         | 
| 10 | 
            +
            ~~閉路の判定は、(実際に辿ってみなくても)各点から出る辺の数によって判断出来るのではないでしょうか。
         | 
| 11 11 | 
             
            点から1本だけ辺が出ていれば、開いている部分があります。
         | 
| 12 12 | 
             
            点から3本以上辺が出ていれば、完全な閉路は出来なくなりますし、一部が閉路になった可能性があります。
         | 
| 13 13 | 
             
            全ての点から2本の辺が出ていれば、完全な閉路が出来たということでしょう。
         | 
| 14 14 | 
             
            これらの条件の組み合わせを考えれば判断出来るものと思います。
         | 
| 15 | 
            -
             | 
| 15 | 
            +
            ※ざっくり考えたものですので穴がある可能性があります。~~
         | 
| 16 16 |  | 
| 17 17 | 
             
            valid 関数を check に名前を変えて、戻り値を DISCARD/CONTINUE/COMPLETE の 3 つとして状況を返すようにしました。
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            間違いを指摘頂きまして、結局最後に追加された辺から辿ることになりました。
         | 
| 20 | 
            +
            間違ったコードのままよりは良いかなと・・・**これが間違っていないとは言い切れません**が。
         | 
| 18 21 | 
             
            ```c
         | 
| 19 22 | 
             
            #include <stdio.h>
         | 
| 23 | 
            +
            #include <stdlib.h>
         | 
| 24 | 
            +
            #include <string.h>
         | 
| 20 25 |  | 
| 26 | 
            +
            //#define TEST
         | 
| 27 | 
            +
            #define CHECK_LOG
         | 
| 28 | 
            +
             | 
| 21 29 | 
             
            typedef struct {
         | 
| 22 30 | 
             
              int u; //点1
         | 
| 23 31 | 
             
              int v; //点2
         | 
| 24 32 | 
             
              double dist; //点間の距離
         | 
| 25 33 | 
             
            } Adjacent;
         | 
| 26 34 |  | 
| 35 | 
            +
            typedef struct {
         | 
| 36 | 
            +
              int p, c;
         | 
| 37 | 
            +
            } PC;
         | 
| 38 | 
            +
             | 
| 27 39 | 
             
            //判定
         | 
| 28 40 | 
             
            #define DISCARD (-1) //(最期に追加した辺を)破棄
         | 
| 29 41 | 
             
            #define CONTINUE (0) //継続
         | 
| 30 42 | 
             
            #define COMPLETE (1) //完了
         | 
| 43 | 
            +
             | 
| 31 44 | 
             
            int check(int n, int c, Adjacent **result) {
         | 
| 45 | 
            +
            #ifdef CHECK_LOG
         | 
| 46 | 
            +
              printf("n=%d,c=%d\n", n, c);
         | 
| 47 | 
            +
              for(int i=0; i<c; i++) printf("%d-%d\n", result[i]->u, result[i]->v);
         | 
| 48 | 
            +
            #endif //CHECK_LOG
         | 
| 49 | 
            +
             | 
| 50 | 
            +
              if(c > n) return DISCARD; //辺が多くなったなら破棄
         | 
| 51 | 
            +
             | 
| 52 | 
            +
              int rinf = CONTINUE;
         | 
| 53 | 
            +
              int hasClosed = 0; //false
         | 
| 54 | 
            +
             | 
| 55 | 
            +
              //最期の辺(result[c-1])の接続先を追う
         | 
| 56 | 
            +
              Adjacent **cpy = memcpy(malloc(sizeof(Adjacent*) * c), result, sizeof(Adjacent*) * c);
         | 
| 57 | 
            +
              PC *q = memset(malloc(sizeof(PC) * n), 0, sizeof(PC) * n);
         | 
| 58 | 
            +
             | 
| 32 | 
            -
              int  | 
| 59 | 
            +
              int wi = 0, ri = 0;
         | 
| 60 | 
            +
              q[wi].p = cpy[c-1]->u; //最後に追加した辺の両端を追加
         | 
| 61 | 
            +
              q[wi++].c = 1;
         | 
| 62 | 
            +
              q[wi].p = cpy[c-1]->v;
         | 
| 63 | 
            +
              q[wi++].c = 1;
         | 
| 64 | 
            +
              cpy[c-1] = NULL;
         | 
| 33 | 
            -
               | 
| 65 | 
            +
              while(ri < wi) {
         | 
| 66 | 
            +
                PC *pc = &q[ri++];
         | 
| 67 | 
            +
                for(int i=0; i<c-1; i++) { //点 p に繋がっている辺を cpy から探し、 p の逆側の点を q に追加、辺を cpy から削除
         | 
| 68 | 
            +
                  if(cpy[i] == NULL || (cpy[i]->u != pc->p && cpy[i]->v != pc->p)) continue;
         | 
| 69 | 
            +
                  if(++pc->c > 2) rinf = DISCARD;
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                  int np = pc->p == cpy[i]->u ? cpy[i]->v : cpy[i]->u; //p の逆側の点
         | 
| 72 | 
            +
                  cpy[i] = NULL;
         | 
| 73 | 
            +
             | 
| 34 | 
            -
             | 
| 74 | 
            +
                  int found = 0; //false
         | 
| 35 | 
            -
                for(int j=0; j<c; j++) if(result[j]->u == i || result[j]->v == i) count ++;
         | 
| 36 | 
            -
             | 
| 75 | 
            +
                  for(int j=0; j<wi; j++) { //過去の点に戻った?
         | 
| 76 | 
            +
                    if(q[j].p == np) {
         | 
| 77 | 
            +
                      hasClosed = 1; //true
         | 
| 78 | 
            +
                      found = 1; //true
         | 
| 79 | 
            +
                      if(++q[j].c > 2) rinf = DISCARD;
         | 
| 80 | 
            +
                    }
         | 
| 81 | 
            +
                  }
         | 
| 82 | 
            +
                  if(!found) {
         | 
| 83 | 
            +
                    q[wi].p = np;
         | 
| 37 | 
            -
             | 
| 84 | 
            +
                    q[wi++].c = 1;
         | 
| 85 | 
            +
                  }
         | 
| 86 | 
            +
                }
         | 
| 38 87 | 
             
              }
         | 
| 88 | 
            +
             | 
| 89 | 
            +
            #ifdef CHECK_LOG
         | 
| 90 | 
            +
              printf("wi=%d\n", wi);
         | 
| 39 | 
            -
               | 
| 91 | 
            +
              for(int i=0; i<wi; i++) printf("p=%d,c=%d\n", q[i].p, q[i].c);
         | 
| 92 | 
            +
            #endif //CHECK_LOG
         | 
| 93 | 
            +
             | 
| 94 | 
            +
              if(hasClosed) {
         | 
| 95 | 
            +
                rinf = DISCARD;
         | 
| 96 | 
            +
                if(wi == n) {
         | 
| 97 | 
            +
                  int count = 0;
         | 
| 98 | 
            +
                  for(int i=0; i<wi; i++) if(q[i].c == 2) count ++;
         | 
| 40 | 
            -
             | 
| 99 | 
            +
                  if(count == n) rinf = COMPLETE; //点全部が 2 辺と接続した閉路なら COMPLETE
         | 
| 100 | 
            +
                }
         | 
| 101 | 
            +
              }
         | 
| 102 | 
            +
             | 
| 103 | 
            +
              free(cpy);
         | 
| 104 | 
            +
              free(q);
         | 
| 105 | 
            +
             | 
| 106 | 
            +
            #ifdef CHECK_LOG
         | 
| 107 | 
            +
              printf("rinf=%d\n", rinf);
         | 
| 41 | 
            -
             | 
| 108 | 
            +
            #endif //CHECK_LOG
         | 
| 109 | 
            +
              return rinf;
         | 
| 42 110 | 
             
            }
         | 
| 43 111 |  | 
| 44 112 | 
             
            //greedy法
         | 
| @@ -71,6 +139,37 @@ | |
| 71 139 | 
             
            }
         | 
| 72 140 |  | 
| 73 141 | 
             
            int main(void) {
         | 
| 142 | 
            +
            #ifdef TEST
         | 
| 143 | 
            +
              printf("TEST start\n");
         | 
| 144 | 
            +
              Adjacent testdata1[] = {
         | 
| 145 | 
            +
                  {0,1,100},
         | 
| 146 | 
            +
                  {2,3,110},
         | 
| 147 | 
            +
                  {3,4,120},
         | 
| 148 | 
            +
                  {2,4,130},
         | 
| 149 | 
            +
              };
         | 
| 150 | 
            +
              Adjacent *test1[] = {
         | 
| 151 | 
            +
                  &testdata1[0],
         | 
| 152 | 
            +
                  &testdata1[1],
         | 
| 153 | 
            +
                  &testdata1[2],
         | 
| 154 | 
            +
                  &testdata1[3],
         | 
| 155 | 
            +
              };
         | 
| 156 | 
            +
              if(check(5, 4, test1) != DISCARD) printf("%d error\n", __LINE__);
         | 
| 157 | 
            +
             | 
| 158 | 
            +
              Adjacent testdata2[4] = {
         | 
| 159 | 
            +
                  {0,2,100},
         | 
| 160 | 
            +
                  {2,3,110},
         | 
| 161 | 
            +
                  {3,4,120},
         | 
| 162 | 
            +
                  {1,4,130},
         | 
| 163 | 
            +
              };
         | 
| 164 | 
            +
              Adjacent *test2[] = {
         | 
| 165 | 
            +
                  &testdata2[0],
         | 
| 166 | 
            +
                  &testdata2[1],
         | 
| 167 | 
            +
                  &testdata2[2],
         | 
| 168 | 
            +
                  &testdata2[3],
         | 
| 169 | 
            +
              };
         | 
| 170 | 
            +
              if(check(5, 4, test2) != CONTINUE) printf("%d error\n", __LINE__);
         | 
| 171 | 
            +
              printf("end\n");
         | 
| 172 | 
            +
            #else //TEST
         | 
| 74 173 | 
             
              //ファイル読み込み・ソート等を省略
         | 
| 75 174 | 
             
              int n = 5; //点の数
         | 
| 76 175 | 
             
              int m = 10; //辺の数
         | 
| @@ -95,11 +194,121 @@ | |
| 95 194 | 
             
              } else {
         | 
| 96 195 | 
             
                printf("Failure\n");
         | 
| 97 196 | 
             
              }
         | 
| 98 | 
            -
             | 
| 197 | 
            +
            #endif //TEST
         | 
| 99 198 | 
             
              return 0;
         | 
| 100 199 | 
             
            }
         | 
| 101 200 | 
             
            ```
         | 
| 102 201 | 
             
            ```
         | 
| 202 | 
            +
            n=5,c=1
         | 
| 203 | 
            +
            1-3
         | 
| 204 | 
            +
            wi=2
         | 
| 205 | 
            +
            p=1,c=1
         | 
| 206 | 
            +
            p=3,c=1
         | 
| 207 | 
            +
            rinf=0
         | 
| 208 | 
            +
            n=5,c=2
         | 
| 209 | 
            +
            1-3
         | 
| 210 | 
            +
            0-3
         | 
| 211 | 
            +
            wi=3
         | 
| 212 | 
            +
            p=0,c=1
         | 
| 213 | 
            +
            p=3,c=2
         | 
| 214 | 
            +
            p=1,c=1
         | 
| 215 | 
            +
            rinf=0
         | 
| 216 | 
            +
            n=5,c=3
         | 
| 217 | 
            +
            1-3
         | 
| 218 | 
            +
            0-3
         | 
| 219 | 
            +
            0-1
         | 
| 220 | 
            +
            wi=3
         | 
| 221 | 
            +
            p=0,c=2
         | 
| 222 | 
            +
            p=1,c=2
         | 
| 223 | 
            +
            p=3,c=2
         | 
| 224 | 
            +
            rinf=-1
         | 
| 225 | 
            +
            n=5,c=3
         | 
| 226 | 
            +
            1-3
         | 
| 227 | 
            +
            0-3
         | 
| 228 | 
            +
            1-4
         | 
| 229 | 
            +
            wi=4
         | 
| 230 | 
            +
            p=1,c=2
         | 
| 231 | 
            +
            p=4,c=1
         | 
| 232 | 
            +
            p=3,c=2
         | 
| 233 | 
            +
            p=0,c=1
         | 
| 234 | 
            +
            rinf=0
         | 
| 235 | 
            +
            n=5,c=4
         | 
| 236 | 
            +
            1-3
         | 
| 237 | 
            +
            0-3
         | 
| 238 | 
            +
            1-4
         | 
| 239 | 
            +
            0-2
         | 
| 240 | 
            +
            wi=5
         | 
| 241 | 
            +
            p=0,c=2
         | 
| 242 | 
            +
            p=2,c=1
         | 
| 243 | 
            +
            p=3,c=2
         | 
| 244 | 
            +
            p=1,c=2
         | 
| 245 | 
            +
            p=4,c=1
         | 
| 246 | 
            +
            rinf=0
         | 
| 247 | 
            +
            n=5,c=5
         | 
| 248 | 
            +
            1-3
         | 
| 249 | 
            +
            0-3
         | 
| 250 | 
            +
            1-4
         | 
| 251 | 
            +
            0-2
         | 
| 252 | 
            +
            2-3
         | 
| 253 | 
            +
            wi=5
         | 
| 254 | 
            +
            p=2,c=2
         | 
| 255 | 
            +
            p=3,c=3
         | 
| 256 | 
            +
            p=0,c=2
         | 
| 257 | 
            +
            p=1,c=2
         | 
| 258 | 
            +
            p=4,c=1
         | 
| 259 | 
            +
            rinf=-1
         | 
| 260 | 
            +
            n=5,c=5
         | 
| 261 | 
            +
            1-3
         | 
| 262 | 
            +
            0-3
         | 
| 263 | 
            +
            1-4
         | 
| 264 | 
            +
            0-2
         | 
| 265 | 
            +
            3-4
         | 
| 266 | 
            +
            wi=5
         | 
| 267 | 
            +
            p=3,c=3
         | 
| 268 | 
            +
            p=4,c=2
         | 
| 269 | 
            +
            p=1,c=2
         | 
| 270 | 
            +
            p=0,c=2
         | 
| 271 | 
            +
            p=2,c=1
         | 
| 272 | 
            +
            rinf=-1
         | 
| 273 | 
            +
            n=5,c=5
         | 
| 274 | 
            +
            1-3
         | 
| 275 | 
            +
            0-3
         | 
| 276 | 
            +
            1-4
         | 
| 277 | 
            +
            0-2
         | 
| 278 | 
            +
            1-2
         | 
| 279 | 
            +
            wi=5
         | 
| 280 | 
            +
            p=1,c=3
         | 
| 281 | 
            +
            p=2,c=2
         | 
| 282 | 
            +
            p=3,c=2
         | 
| 283 | 
            +
            p=4,c=1
         | 
| 284 | 
            +
            p=0,c=2
         | 
| 285 | 
            +
            rinf=-1
         | 
| 286 | 
            +
            n=5,c=5
         | 
| 287 | 
            +
            1-3
         | 
| 288 | 
            +
            0-3
         | 
| 289 | 
            +
            1-4
         | 
| 290 | 
            +
            0-2
         | 
| 291 | 
            +
            0-4
         | 
| 292 | 
            +
            wi=5
         | 
| 293 | 
            +
            p=0,c=3
         | 
| 294 | 
            +
            p=4,c=2
         | 
| 295 | 
            +
            p=3,c=2
         | 
| 296 | 
            +
            p=2,c=1
         | 
| 297 | 
            +
            p=1,c=2
         | 
| 298 | 
            +
            rinf=-1
         | 
| 299 | 
            +
            n=5,c=5
         | 
| 300 | 
            +
            1-3
         | 
| 301 | 
            +
            0-3
         | 
| 302 | 
            +
            1-4
         | 
| 303 | 
            +
            0-2
         | 
| 304 | 
            +
            2-4
         | 
| 305 | 
            +
            wi=5
         | 
| 306 | 
            +
            p=2,c=2
         | 
| 307 | 
            +
            p=4,c=2
         | 
| 308 | 
            +
            p=0,c=2
         | 
| 309 | 
            +
            p=1,c=2
         | 
| 310 | 
            +
            p=3,c=2
         | 
| 311 | 
            +
            rinf=1
         | 
| 103 312 | 
             
            Final Path: 1 -> 3 -> 0 -> 2 -> 4 -> 1
         | 
| 104 313 | 
             
            Total Distance: 3311.1
         | 
| 105 314 | 
             
            ```
         | 
4
コード修正
    
        answer	
    CHANGED
    
    | @@ -55,7 +55,7 @@ | |
| 55 55 |  | 
| 56 56 | 
             
            //表示
         | 
| 57 57 | 
             
            void print(int c, Adjacent **result) {
         | 
| 58 | 
            -
              printf("Final Path: "); | 
| 58 | 
            +
              printf("Final Path: ");
         | 
| 59 59 | 
             
              double total = 0;
         | 
| 60 60 | 
             
              int i = 0;
         | 
| 61 61 | 
             
              int p = result[i]->u;
         | 
3
コード修正: check 関数の戻り値を追加
    
        answer	
    CHANGED
    
    | @@ -13,6 +13,8 @@ | |
| 13 13 | 
             
            全ての点から2本の辺が出ていれば、完全な閉路が出来たということでしょう。
         | 
| 14 14 | 
             
            これらの条件の組み合わせを考えれば判断出来るものと思います。
         | 
| 15 15 | 
             
            **※ざっくり考えたものですので穴がある可能性があります。**
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            valid 関数を check に名前を変えて、戻り値を DISCARD/CONTINUE/COMPLETE の 3 つとして状況を返すようにしました。
         | 
| 16 18 | 
             
            ```c
         | 
| 17 19 | 
             
            #include <stdio.h>
         | 
| 18 20 |  | 
| @@ -23,25 +25,32 @@ | |
| 23 25 | 
             
            } Adjacent;
         | 
| 24 26 |  | 
| 25 27 | 
             
            //判定
         | 
| 28 | 
            +
            #define DISCARD (-1) //(最期に追加した辺を)破棄
         | 
| 29 | 
            +
            #define CONTINUE (0) //継続
         | 
| 30 | 
            +
            #define COMPLETE (1) //完了
         | 
| 26 | 
            -
            int  | 
| 31 | 
            +
            int check(int n, int c, Adjacent **result) {
         | 
| 27 32 | 
             
              int open = 0;
         | 
| 28 33 | 
             
              for(int i=0; i<n; i++) {
         | 
| 29 34 | 
             
                int count = 0; //点i が現れる数
         | 
| 30 35 | 
             
                for(int j=0; j<c; j++) if(result[j]->u == i || result[j]->v == i) count ++;
         | 
| 31 | 
            -
                if(count > 2) return  | 
| 36 | 
            +
                if(count > 2) return DISCARD; // 1 つの点から 3 本以上辺が出ているなら破棄
         | 
| 32 37 | 
             
                open |= count == 1;
         | 
| 33 38 | 
             
              }
         | 
| 34 | 
            -
              if(c < n) return open; //辺がまだ足りないなら開いていなければならない
         | 
| 39 | 
            +
              if(c < n) return open ? CONTINUE : DISCARD; //辺がまだ足りないなら開いていなければならない
         | 
| 35 | 
            -
              if(c == n) return  | 
| 40 | 
            +
              if(c == n) return open ? DISCARD : COMPLETE; //辺が足りたなら閉じていなければならない
         | 
| 36 | 
            -
              return  | 
| 41 | 
            +
              return DISCARD; //辺が多くなったなら破棄
         | 
| 37 42 | 
             
            }
         | 
| 38 43 |  | 
| 39 44 | 
             
            //greedy法
         | 
| 40 | 
            -
             | 
| 45 | 
            +
            int greedy(int n, int m, Adjacent *adjacent, Adjacent **result) {
         | 
| 41 46 | 
             
              for(int i=0, c=0; i<m; i++) {
         | 
| 42 | 
            -
                result[c] = &adjacent[i];
         | 
| 47 | 
            +
                result[c++] = &adjacent[i];
         | 
| 43 | 
            -
                 | 
| 48 | 
            +
                switch(check(n, c, result)) {
         | 
| 49 | 
            +
                case COMPLETE: return c;
         | 
| 50 | 
            +
                case DISCARD: c--;
         | 
| 51 | 
            +
                }
         | 
| 44 52 | 
             
              }
         | 
| 53 | 
            +
              return 0;
         | 
| 45 54 | 
             
            }
         | 
| 46 55 |  | 
| 47 56 | 
             
            //表示
         | 
| @@ -75,14 +84,17 @@ | |
| 75 84 | 
             
                  {3,4, 871.2},
         | 
| 76 85 | 
             
                  {1,2, 1015.1},
         | 
| 77 86 | 
             
                  {0,4, 1055.9},
         | 
| 78 | 
            -
                  {2,4, 1592.3}
         | 
| 87 | 
            +
                  {2,4, 1592.3},
         | 
| 79 88 | 
             
              };
         | 
| 80 89 | 
             
              Adjacent *result[10] = {0}; //結果保存領域(adjacents の要素へのポインタ)
         | 
| 81 90 |  | 
| 82 | 
            -
              greedy(n, m, adjacents, result);
         | 
| 91 | 
            +
              int c = greedy(n, m, adjacents, result);
         | 
| 83 92 |  | 
| 93 | 
            +
              if(c == n) {
         | 
| 84 | 
            -
             | 
| 94 | 
            +
                print(c, result); //最終的な経路を表示
         | 
| 95 | 
            +
              } else {
         | 
| 85 | 
            -
             | 
| 96 | 
            +
                printf("Failure\n");
         | 
| 97 | 
            +
              }
         | 
| 86 98 |  | 
| 87 99 | 
             
              return 0;
         | 
| 88 100 | 
             
            }
         | 
2
追加
    
        answer	
    CHANGED
    
    | @@ -6,6 +6,13 @@ | |
| 6 6 | 
             
            3. 辺の数が多くなった場合:false
         | 
| 7 7 |  | 
| 8 8 | 
             
            1 と 2 で閉路の扱いが逆ですので、判断もそのようにする必要があると思います。
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            閉路の判定は、(実際に辿ってみなくても)各点から出る辺の数によって判断出来るのではないでしょうか。
         | 
| 11 | 
            +
            点から1本だけ辺が出ていれば、開いている部分があります。
         | 
| 12 | 
            +
            点から3本以上辺が出ていれば、完全な閉路は出来なくなりますし、一部が閉路になった可能性があります。
         | 
| 13 | 
            +
            全ての点から2本の辺が出ていれば、完全な閉路が出来たということでしょう。
         | 
| 14 | 
            +
            これらの条件の組み合わせを考えれば判断出来るものと思います。
         | 
| 15 | 
            +
            **※ざっくり考えたものですので穴がある可能性があります。**
         | 
| 9 16 | 
             
            ```c
         | 
| 10 17 | 
             
            #include <stdio.h>
         | 
| 11 18 |  | 
1
説明修正
    
        answer	
    CHANGED
    
    | @@ -1,4 +1,11 @@ | |
| 1 | 
            +
            valid 関数は、最後に追加した辺を用いるかどうかを返します。
         | 
| 2 | 
            +
            最後に追加した辺を用いるかどうかは、以下の点で判断出来ます。
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            1. 辺の数が全ての点を回るのに不足している場合:閉路が出来たら false, 出来なかったなら true
         | 
| 5 | 
            +
            2. 辺の数が全ての点を回るのに必要な数に達した場合:完全な閉路が出来たら true, 出来なかったら false
         | 
| 6 | 
            +
            3. 辺の数が多くなった場合:false
         | 
| 7 | 
            +
             | 
| 1 | 
            -
             | 
| 8 | 
            +
            1 と 2 で閉路の扱いが逆ですので、判断もそのようにする必要があると思います。
         | 
| 2 9 | 
             
            ```c
         | 
| 3 10 | 
             
            #include <stdio.h>
         | 
| 4 11 |  | 
