版权声明:是自己手打的没错 https://blog.csdn.net/Mr_Treeeee/article/details/82319811
https://arc102.contest.atcoder.jp/tasks/arc102_b
题意:
给你一个L,让你构造一张图,点数不超过20,边数不超过60。可以重边。
他的拓扑排序必须为1 2 3…… n,即边只能从小连到大。
这张图必须确切存在L条不同的边,长度分别为0,1,2,3……L-1.
L=<1e6
POINT:
如果L是1,2,4,8,16这种整二进制数,很好办。只要给i到i+1连上0和1<<(i-1)的两条边就可以。
问题出在把这个整二进制数处理完了之后,后面还有1怎么办。比如这个数(45)。
最前面的32很好办。就按照之前的方法可以构造完0到31。剩下来的1,4,8个数。
分别是(32),(33,34,35,36),(37,38,39,40,41,42,43)
这时候,加一条边i到n,长度为x,则会增加x,x+1,……,x+2^(i-1)-1那么多边。
所以 加 1-n 长度为32, 3-n 长度为33, 4-n长度为37。这三条边。
至于32,33,37这三个长度是怎么算的,看规律便能知晓。
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
struct node
{
int u,v,w;
};
node a[70];
int cnt=0;
void add(int u,int v,int w)
{
cnt++;
a[cnt].u=u;a[cnt].v=v;a[cnt].w=w;
}
int main()
{
int L;
scanf("%d",&L);
int tmp=L;
int n=0;
while(tmp){
n++;
tmp>>=1;
}
for(int i=1;i<n;i++){
add(i,i+1,1<<(i-1));
add(i,i+1,0);
}
int w=1<<(n-1),k=1;;
while(L!=1){
if(L&1) {
add(k,n,w);
w|=1<<(k-1);
}
k++;
L>>=1;
}
printf("%d %d\n",n,cnt);
for(int i=1;i<=cnt;i++){
printf("%d %d %d\n",a[i].u,a[i].v,a[i].w);
}
return 0;
}