Tags: graphs path-traversal 

Rating: 5.0

At first glance, this appears to be some sort of pathing problem, and we realized that the [Floyd-Warshall Algorithm](https://en.wikipedia.org/wiki/Floyd–Warshall_algorithm) would be appropriate. However, we needed to tweak it for our needs. Instead of computing/storing the lengths of the shortest paths, we instead compute/store the minimum resistance value on the paths, then update the paths so that the "longest path" (i.e. the one with the greatest least resistance) will be preferred.

Regarding the actual challenge, it took a while to figure out the right output format. It turns out the output has to be separated by newlines, but a newline cannot come after the last output line for a graph, else the server parses it incorrectly and gives `WRONG ANSWER`. The code below assumes that the node names are integers, even though the problem says they are strings, and that the node numbers in the given graphs never exceed 99 (index 100).

```
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>

using namespace std;

// ========================================================================
pid_t connect(const char *hostport, FILE* &inf, FILE* &outf);
// ========================================================================

#define SIZE 100
#define LINE_SIZE 200

int first = 0;
int minNode = 1000;
int maxNode = -1000;
int board[SIZE][SIZE];
char line[LINE_SIZE];
char answer[5000];

// ========================================================================

void readData(FILE* in)
{
int one, two, three;

// initialize the board
for (int i = 0; i < SIZE; i++)
{
for (int j = 0; j < SIZE; j++)
{
board[i][j] = -1000;
}
}

// while there are connections to be read in
while (sscanf(line, "%d %d %d", &one, &two, &three) == 3)
{
printf("connection: %s", line);
board[one][two] = three;
board[two][one] = three;

if (one < minNode) minNode = one;
if (two < minNode) minNode = two;
if (one > maxNode) maxNode = one;
if (two > maxNode) maxNode = two;

fgets(line, LINE_SIZE, in);
}

maxNode++; // make it one greater for nice for loop bounds
}

// ========================================================================

void floydWarshall()
{
// compute everything
for (int k = minNode; k < maxNode; k++) // intermediate
{
for (int i = minNode; i < maxNode; i++) // from
{
for (int j = minNode; j < maxNode; j++) // to
{
if ((i == k) || (j == k) || (i == j)) continue; // is a loop
if ((board[i][k] < 0) || (board[k][j] < 0)) continue; // no path possible

int testr = (board[i][k] < board[k][j] ? board[i][k] : board[k][j]);

// if more resistant, combine paths ik and kj into one path
if (testr > board[i][j])
{
board[i][j] = testr;
}
}
}
}
}

// ========================================================================

void solve(FILE* in, FILE* out)
{
int from;
int to;
char* loc = &answer[0];

printf("solving %s", line);

// we can start out doing this because the first line is already in the line buffer
// since we had to read it to know when to stop reading edge definitions
while (sscanf(line, "%d %d", &from, &to) == 2)
{
loc += sprintf(loc, "%.1f\n", (float)board[from][to]);
printf("solved %s", line);

if (fgets(line, LINE_SIZE, in) == 0)
{
break;
}
}

loc[-1] = '\0'; // lop off the last newline

printf("%s", answer);
fprintf(out, "%s", answer);
fflush(out);
}

// ========================================================================

int main()
{
FILE* in = stdin;
FILE* out = stdout;

connect("programming.pwn2win.party:9002", in, out);

while (fgets(line, LINE_SIZE, in) != 0)
{
printf("%s", line);

readData(in);
floydWarshall();
solve(in, out);

printf("%s", line);
}

return 0;
}

// ========================================================================

pid_t connect(const char *hostport, FILE* &inf, FILE* &outf) {
int pipein[2], pipeout[2];
if (pipe(pipein) != 0 || pipe(pipeout) != 0) {
perror("pipe");
exit(1);
}

const pid_t pid = fork();
if (pid == 0) { // Child
close(pipeout[1]);
dup2(pipeout[0], STDIN_FILENO);
close(pipein[0]);
dup2(pipein[1], STDOUT_FILENO);
execlp("openssl",
"openssl", "s_client",
"-CAfile", "/etc/ssl/certs/ca-certificates.crt",
"-quiet",
"-verify", "true",
"-connect", hostport,
(const char*)NULL);
perror("execl");
exit(1);
}

if ((inf = fdopen(pipein[0], "r")) == NULL
|| (outf = fdopen(pipeout[1], "w")) == NULL) {
perror("fdopen");
exit(1);
}
setvbuf(inf, NULL, _IONBF, 0);
setvbuf(outf, NULL, _IONBF, 0);
return pid;
}

// ========================================================================

```