#include #include // Graf (typy a proměnné) struct edge_t { // Konec hrany size_t end_vertex; // Její obtížnost int difficulty; }; struct vertex_t { // Index první hrany ven z tohoto vrcholu size_t first_edge; // Která je naše první nepoužitá? size_t current_edge; }; static struct vertex_t *vertices; static size_t vertex_count; static struct edge_t *edges; static size_t edge_count; // Eulerův tah. Poznamenáváme si indexy použitých hran. static size_t *tour; static size_t tour_pos; // Rekurzivní DFS, které počítá eulerův tah static void euler_dfs(size_t vertex) { // Zbývá ještě nějaká nepoužitá? while (vertices[vertex].current_edge < vertices[vertex + 1].first_edge) { // Použijeme jednu hranu size_t current = vertices[vertex].current_edge ++; // Vydáme se po ní euler_dfs(edges[current].end_vertex); // Zaznamenáme si ji, když se z ní vrátíme tour[tour_pos ++] = current; } } int main(int argc, char *argv[]) { /* * Načtení grafu * ============= * Předpokládáme, že graf je zadán tak, že na prvním řádku je počet vrcholů a hran. * Dále následují sekce pro jednotlivé vrcholy (číslované od 0). Každá sekce * začíná počtem hran vycházejících z tohoto vrcholu a správným počtem hran, * každá jako dvojice koncový vrchol, obtížnost. Graf by mohl vypadat třeba takto: * 3 3 * 0 (nultý vrchol nemá žádné hrany ven) * 2 (z prvního vedou dvě) * 0 2 (hrana do nultého vrcholu obtížnosti 2) * 2 -1 * 1 * 0 4 */ // Kolik je celkem křižovatek/vrcholů a cest/hran? scanf("%zd%zd", &vertex_count, &edge_count); // Připravíme si prázdná pole (jeden vrchol navíc, zarážka) vertices = calloc(vertex_count + 1, sizeof *vertices); edges = calloc(edge_count, sizeof *edges); for (size_t i = 0; i < vertex_count; ++ i) { // Počet hran ven z tohoto vrcholu size_t local_edge_count; scanf("%zd", &local_edge_count); // Naše první nepoužitá je naše první vertices[i].current_edge = vertices[i].first_edge; // Další vrchol začíná o tolik hran dále vertices[i + 1].first_edge = vertices[i].first_edge + local_edge_count; // Jednotlivé hrany for (size_t j = vertices[i].first_edge; j < vertices[i + 1].first_edge; ++ j) scanf("%zd%d", &edges[j].end_vertex, &edges[j].difficulty); } // Místo na eulerův tah tour = calloc(edge_count, sizeof *tour); // Spočítáme tah euler_dfs(0); // Vrcholy už nám k ničemu nejsou free(vertices); vertices = NULL; // Proscanujeme tah. Lezeme odzadu, je v poli pozpátku. size_t best_start = edge_count - 1, start_vertex = 0; int best_sum = 0, current_sum = 0; // Projdeme pozpátku for (ssize_t i = edge_count - 1; i >= 0; -- i) { current_sum += edges[tour[i]].difficulty; if (current_sum < best_sum) { // Chceme začít od následující hrany best_sum = current_sum; best_start = i - 1; start_vertex = edges[tour[i]].end_vertex; } } // Cesta je více do kopce než z kopce, nemá řešení if (current_sum < 0) { printf("No, dáš si do těla\n"); free(edges); free(tour); return 0; } // Začínáme v tomto nejlepším vrcholu printf("%zd\n", start_vertex); // Projdeme hrany jako v cyklickém poli, pozpátku, vypisujeme vrcholy size_t i = (best_start + edge_count) % edge_count; // Tento do - while je jediný kus, který nefunguje při prázdném grafu, šlo by ošetřit zvlášť do { printf("%zd\n", edges[tour[i]].end_vertex); // Přesun na další hranu, cyklicky i = (i - 1 + edge_count) % edge_count; // Končíme ve chvíli, kdy se znovu podíváme na tu počáteční hranu } while (i != best_start); // Uklizení free(edges); free(tour); return 0; }