@All Your Paths are Different Lengths@
@题目描述 - English@
Time limit : 2sec / Memory limit : 1024MB
Score : 700 points
Problem Statement
You are given an integer L. Construct a directed graph that satisfies the conditions below. The graph may contain multiple edges between the same pair of vertices. It can be proved that such a graph always exists.
The number of vertices, N, is at most 20. The vertices are given ID numbers from 1 to N.
The number of edges, M, is at most 60. Each edge has an integer length between 0 and 10^6 (inclusive).
Every edge is directed from the vertex with the smaller ID to the vertex with the larger ID. That is, 1,2,…,N is one possible topological order of the vertices.
There are exactly L different paths from Vertex 1 to Vertex N. The lengths of these paths are all different, and they are integers between 0 and L−1.
Here, the length of a path is the sum of the lengths of the edges contained in that path, and two paths are considered different when the sets of the edges contained in those paths are different.
Constraints
2≤L≤10^6
L is an integer.
Input
Input is given from Standard Input in the following format:
L
Output
In the first line, print N and M, the number of the vertices and edges in your graph. In the i-th of the following M lines, print three integers ui,vi and wi, representing the starting vertex, the ending vertex and the length of the i-th edge. If there are multiple solutions, any of them will be accepted.
Sample Input 1
4
Sample Output 1
8 10
1 2 0
2 3 0
3 4 0
1 5 0
2 6 0
3 7 0
4 8 0
5 6 1
6 7 1
7 8 1
In the graph represented by the sample output, there are four paths from Vertex 1 to N=8:
1 → 2 → 3 → 4 → 8 with length 0
1 → 2 → 3 → 7 → 8 with length 1
1 → 2 → 6 → 7 → 8 with length 2
1 → 5 → 6 → 7 → 8 with length 3
There are other possible solutions.
Sample Input 2
5
Sample Output 2
5 7
1 2 0
2 3 1
3 4 0
4 5 0
2 4 0
1 3 3
3 5 1
@大致题意@
构造一个 n 点 m 边的有向带权图,要求边必须从节点编号小的连向结点编号大的。允许重边。要使得从结点 1 到结点 n 恰好有 L 条路径,这 L 条路径的长度互不相同且在[0,L-1]范围内。
n<=20, m<=60, L<=10^6
@分析1@
【蛮有趣的构造题】
首先观察数据范围,发现2^20 = 1048576 ≈ 1000000 = 10^6……
你要说这是巧合我绝对不信。
然后,注意到题目特别提到了“重边”。
然后,“用几个数之和表示[0,L-1]的所有数”,如果单看这个没什么思路,但如果结合上面数据范围的话……
用二进制表达。
两个点之间连两条边,权值分别为0与2^i。
大致的构造思路就差不多是这样,详细细节在下面。
@分析2@
我们不妨总是令n=20。
对于2<=i<=19的结点,我们i与i+1之间连两条边,一条权值为 0 0 ,一条权值为
。
这样,如果1号结点向i号结点连一条权值为w的边,那么从1到20就会出现 w+[0...220−i−1] w + [ 0...2 20 − i − 1 ] 的所有数。
接下来?我们不妨采用数位dp的思想。
假设将L转化成二进制形式,即令