题意

构造一棵树,让它有k条直径。边权都是非负整数,要求点数不能超过5000。

$k \leq 5000000$


 

思考

让树根底下分别挂着长度为a,b,c的边权为0的链,然后将链的某一端向根连一条边权为1的边,这样共有ab+ac+bc条直径。可以发现,对于数据范围内的k,可以很快地找到这样的a,b,c。


 

代码

 1 // luogu-judger-enable-o2
 2 // luogu-judger-enable-o2
 3 // luogu-judger-enable-o2
 4 // luogu-judger-enable-o2
 5 #include<bits/stdc++.h>
 6 using namespace std;
 7 typedef unsigned int ui;
 8 ui SEED;
 9 int k;
10 int size,a[5555];
11 int b[5000005];
12 bool vis[5000005];
13 inline int R(int l,int r)
14 {
15     SEED^=SEED<<13;
16     SEED>=SEED>>5;
17     SEED^=1;
18     return SEED%(r-l+1)+l;
19 }
20 int main()
21 {
22 //    freopen("diameter.in","r",stdin);
23 //    freopen("diameter.out","w",stdout);
24     ios::sync_with_stdio(false);
25     for(int i=1;i*i<=5000000;++i)
26         vis[i*i]=1;
27     cin>>k;
28     if(k<=3000)
29     {
30         cout<<k+2<<endl;
31         cout<<k+2<<" "<<1<<" "<<100<<endl;
32         for(int i=1;i<=k;++i)
33             cout<<1<<" "<<i+1<<" "<<1<<endl;
34         return 0;
35     }
36     int base=k;
37     for(int c=sqrt(base);c>=1;--c)
38     {
39         int g=k-c*c;
40         for(int a=1;a*a<=g;++a)
41             for(int b=1;b*b<=g;++b)
42                 if(a*b+a*c+b*c==k)
43                 {
44                     --a,--b,--c;
45                     cout<<a+b+c+4<<endl;
46                     cout<<1<<" "<<2<<" "<<1<<endl;
47                     for(int i=1;i<=a;++i)
48                         cout<<1+i<<" "<<1+i+1<<" "<<0<<endl;
49                     cout<<1<<" "<<2+a+1<<" "<<1<<endl;
50                     for(int i=1;i<=b;++i)
51                         cout<<2+a+i<<" "<<2+a+i+1<<" "<<0<<endl;
52                     cout<<1<<" "<<3+a+b+1<<" "<<1<<endl;
53                     for(int i=1;i<=c;++i)
54                         cout<<3+a+b+i<<" "<<3+a+b+i+1<<" "<<0<<endl;
55                     return 0;
56                 }
57     }
58     return 0;
59 }
View Code

 

 posted on 2019-09-20 08:47  GreenDuck  阅读(154)  评论(0编辑  收藏  举报