How to group items by path (graph structure) and leave only those with highest score using t-sql?
I have completely redone my answer (based on the additional information you provided in your question).  

You indicated that you tried recursion and it was too slow on a large set of data.  I've created a cursor based solution that works on your test data, but I'm wondering if it gives you the correct answer on your production data.  With such a small set of test data, it's difficult to spot flaws in my logic.

Can you give it a try and let me know if I'm any closer to a proper solution?  

DECLARE @OfferId INT
DECLARE @OffersToDelete TABLE (id INT)

--Declare cursor for all Offers
DECLARE _CURSOR CURSOR LOCAL FORWARD_ONLY STATIC READ_ONLY
FOR
SELECT [o].offerid
FROM Offers [o]
ORDER BY [o].OfferId

OPEN _CURSOR

FETCH NEXT
FROM _CURSOR
INTO @OfferId

DECLARE @Related TABLE (OfferId INT)

WHILE @@FETCH_STATUS = 0
BEGIN
    --For each Offer, initialize @Related table
    DELETE
    FROM @Related

    --Insert into @Related the Offerid that we are currently processing
    INSERT INTO @Related
    SELECT [or].OfferId2
    FROM OffersRelation [or]
    WHERE [or].OfferId1 = @OfferId

    --Now, loop through all offers related to the one we're processing
    --When @@ROWCOUNT = 0, you have processed all related rows and need
    --to break out of the while loop
    WHILE 1 = 1
    BEGIN
        INSERT INTO @Related
        SELECT [or].OfferId2
        FROM OffersRelation [or]
        JOIN @Related [r]
            ON [r].OfferId = [or].OfferId1
        WHERE NOT EXISTS (
                SELECT *
                FROM @Related
                WHERE OfferId = [or].OfferId2
                )
            AND [r].OfferId &lt;&gt; @OfferId

        IF @@ROWCOUNT = 0
            BREAK;
    END;

    --With all related rows, including the offer we're processing,
    --add a row number ordered by OfferScore desc and insert all rows
    --not = 1 into the @OffersToDelete table
    WITH OfferAndRelated
    AS (
        SELECT Offerid
            ,offerscore
        FROM offers
        WHERE offerid = @OfferId

        UNION

        SELECT [o].offerid
            ,[o].offerscore
        FROM @Related [r]
        JOIN Offers [o]
            ON [o].OfferId = [r].OfferId
        )
        ,OfferAndRelatedWithRowNumber
    AS (
        SELECT *
            ,ROW_NUMBER() OVER (
                ORDER BY OfferScore DESC
                ) AS rn
        FROM OfferAndRelated
        )
    INSERT INTO @OffersToDelete
    SELECT OfferId
    FROM OfferAndRelatedWithRowNumber
    WHERE rn &lt;&gt; 1

    --  SELECT *
    --  FROM @Related
    FETCH NEXT
    FROM _CURSOR
    INTO @OfferId
END

CLOSE _CURSOR

DEALLOCATE _CURSOR

--Delete from Offers where the OfferId is on the @OffersToDelete table
DELETE [o]
FROM Offers [o]
JOIN @OffersToDelete otd
    ON otd.id = [o].OfferId

SELECT *
FROM Offers




| OfferId | OfferScore |
|---------|------------|
| 2       | 20         |
| 6       | 6          |
| 8       | 8          |