There might be a cleaner way to do this, but this seems to work:
WITH cteRawData As
(
SELECT
[From],
[To],
'/' + CAST([From] As varchar(max)) + '/' + CAST([To] As varchar(max)) + '/' As [Path],
1 As Depth
FROM
[Table]
UNION ALL
SELECT
F.[From],
T.[To],
F.[Path] + CAST(T.[To] As varchar(max)) + '/',
F.Depth + 1
FROM
cteRawData As F
INNER JOIN [Table] As T
ON T.[From] = F.[To]
WHERE
F.[Path] Not Like '%/' + CAST(T.[To] As varchar(max)) + '/%'
),
cteData As
(
SELECT
[From],
[To],
ROW_NUMBER() OVER (PARTITION BY [From] ORDER BY Depth DESC) As RN
FROM
cteRawData
)
SELECT
[From],
[To]
FROM
cteData
WHERE
RN = 1
ORDER BY
[From]
;