解析:
好一道二进制拆分。。。
令
n
=
f
l
o
o
r
(
l
o
g
2
L
)
n=floor(log_2L)
n=floor(log2L)
其实这道题很容易考虑到二进制拆分,就是每两个点之间加边,
i
i
i和
i
+
1
i+1
i+1连一条0的边和一条
2
i
−
1
2^{i-1}
2i−1的边。那么在
2
n
−
1
2^{n}-1
2n−1以下的所有数都有路径满足并且唯一满足。(注意题目要求只有精确的L条路径,不能多,也不能少)。
剩下的怎么办?为了不让添加的边产生新的路径,我们直接从中间点向最后一个节点加边。。
代码(本来想写 e m p l a c e emplace emplace_ b a c k back back,结果自己的编译器版本太老用不了):
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
#define st static
#define mp make_pair
#define emplace_back push_back
inline
void outint(int a){
st char ch[13];
if(a==0)pc('0');
while(a)ch[++ch[0]]=(a-a/10*10)^48,a/=10;
while(ch[0])pc(ch[ch[0]--]);
}
vector<pair<pair<int,int> ,int > > e;
int main(){
int L;
cin>>L;
int n=0,tmp=L;
while(tmp){
++n,tmp>>=1;
}
for(int re i=1;i<n;++i){
e.emplace_back(mp(mp(i,i+1),0));
e.emplace_back(mp(mp(i,i+1),1<<(i-1)));
}
int w=1<<(n-1),cnt=1;
while(L^1){
if(L&1){
e.emplace_back(mp(mp(cnt,n),w));
w|=1<<(cnt-1);
}
L>>=1;
++cnt;
}
outint(n),pc(' '),outint(e.size()),pc('\n');
for(vector<pair<pair<int,int>,int> >:: iterator it=e.begin();it!=e.end();++it){
outint(it->first.first),pc(' '),outint(it->first.second),pc(' '),outint(it->second),pc('\n');
}
return 0;
}