1. Abridged Problem Statement  
You have N boxes, each containing exactly one coin of distinct integer weights 1 through N. You are given M comparisons of the form “box P is lighter than box Q.” Determine an assignment of coin weights to boxes that satisfies all comparisons, or report “No solution” if none exists. If a solution exists, output a permutation A of 1…N where A[K] is the weight of the coin in box K.

2. Detailed Editorial  

Problem Reduction  
- Each box K must be assigned a distinct integer weight from 1 to N.  
- A comparison “P lighter than Q” enforces weight[P] < weight[Q].  
- These are precedence constraints that form a directed graph on N nodes (boxes).  

We must find a permutation of [1..N] that respects all these constraints or conclude that they are inconsistent (i.e., the graph has a cycle).  

Solution Outline  
1. Build a directed graph G with N vertices (boxes). For each comparison P Q, add edge P→Q.  
2. Detect if G has a cycle and, if not, produce a topological ordering of its vertices.  
   - We use Kahn’s algorithm (BFS-based) for topological sort:  
     a. Compute in-degree for each vertex.  
     b. Initialize a queue with all vertices of in-degree zero.  
     c. While the queue is not empty, pop vertex u, append to topo order, and decrement in-degree of all neighbors v. Whenever in-degree[v] becomes zero, enqueue v.  
     d. If we process fewer than N vertices, a cycle exists.  
3. If a valid topological order `order[]` of length N exists, assign weights in increasing order along that topological order:  
   - The first vertex in `order` gets weight = 1, the second gets 2, …, the N-th gets N.  
4. Finally, output for each box K the assigned weight. If there was a cycle, output “No solution.”

Time Complexity  
- Building the graph: O(N + M).  
- Kahn’s topological sort: O(N + M).  
- Overall: O(N + M), which is efficient for N ≤ 100, M ≤ 10000.

3. C++ Solution
```cpp
#include <bits/stdc++.h>

using namespace std;

template<typename T1, typename T2>
ostream& operator<<(ostream& out, const pair<T1, T2>& x) {
    return out << x.first << ' ' << x.second;
}

template<typename T1, typename T2>
istream& operator>>(istream& in, pair<T1, T2>& x) {
    return in >> x.first >> x.second;
}

template<typename T>
istream& operator>>(istream& in, vector<T>& a) {
    for(auto& x: a) {
        in >> x;
    }
    return in;
};

template<typename T>
ostream& operator<<(ostream& out, const vector<T>& a) {
    for(auto x: a) {
        out << x << ' ';
    }
    return out;
};

int n, m;
vector<vector<int>> adj;

void read() {
    cin >> n >> m;
    adj.assign(n, vector<int>());
    for(int i = 0; i < m; i++) {
        int u, v;
        cin >> u >> v;
        u--, v--;
        adj[u].push_back(v);
    }
}

vector<int> top_sort() {
    vector<int> order;
    vector<int> deg(n);
    for(int u = 0; u < n; u++) {
        for(int v: adj[u]) {
            deg[v]++;
        }
    }

    queue<int> q;
    for(int u = 0; u < n; u++) {
        if(deg[u] == 0) {
            q.push(u);
        }
    }

    while(!q.empty()) {
        int u = q.front();
        q.pop();
        order.push_back(u);
        for(int v: adj[u]) {
            deg[v]--;
            if(deg[v] == 0) {
                q.push(v);
            }
        }
    }

    return order;
}

void solve() {
    // Each weighing "box P lighter than box Q" is a directed edge P -> Q in a
    // DAG whose vertices are the boxes. A valid assignment of coin values is a
    // linear extension of this partial order: run Kahn's topological sort, and
    // the position of a box in the resulting order (1-indexed) is the coin value
    // placed in it. If the topological order does not cover all boxes there is a
    // cycle and no assignment exists.

    vector<int> order = top_sort();
    if((int)order.size() != n) {
        cout << "No solution\n";
        return;
    }

    vector<int> pos(n);
    for(int i = 0; i < n; i++) {
        pos[order[i]] = i;
    }

    for(int i = 0; i < n; i++) {
        cout << pos[i] + 1 << ' ';
    }

    cout << '\n';
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int T = 1;
    // cin >> T;
    for(int test = 1; test <= T; test++) {
        read();
        // cout << "Case #" << test << ": ";
        solve();
    }

    return 0;
}
```

4. Python Solution with Detailed Comments  
```python
import sys
from collections import deque

def main():
    data = sys.stdin.read().split()
    it = iter(data)
    n = int(next(it))
    m = int(next(it))
    # Build adjacency list for a directed graph on n nodes
    adj = [[] for _ in range(n)]
    indeg = [0] * n

    for _ in range(m):
        u = int(next(it)) - 1
        v = int(next(it)) - 1
        # u lighter than v => edge u->v
        adj[u].append(v)
        indeg[v] += 1

    # Kahn's algorithm for topological sorting
    q = deque([u for u in range(n) if indeg[u] == 0])
    order = []

    while q:
        u = q.popleft()
        order.append(u)
        for v in adj[u]:
            indeg[v] -= 1
            if indeg[v] == 0:
                q.append(v)

    # If we did not process all nodes, there is a cycle => no solution
    if len(order) != n:
        print("No solution")
        return

    # pos[u] = index of node u in the topological order
    pos = [0] * n
    for idx, u in enumerate(order):
        pos[u] = idx

    # Assign weights 1..n in topo order, so box u gets pos[u]+1
    result = [str(pos[u] + 1) for u in range(n)]
    print(" ".join(result))


if __name__ == "__main__":
    main()
```

5. Compressed Editorial  
- Model boxes as vertices, comparisons P<Q as directed edges P→Q.  
- Run Kahn’s topological sort to detect cycles and produce an order.  
- If acyclic, assign weights 1..N in that order; otherwise output “No solution.”