题解:P10678 『STA - R6』月
不 简易结论题。
首先明确一下树的直径的定义(也许就我这种蒟蒻赛前都不知道树的直径是啥):树中距离最远的两个点之间的距离被称为树的直径。
那么根据定义我们直接想到一个结论:每次从父节点到子节点连边时我们尽量找度数更多的节点当儿子,先把度数多的节点解决了。
这个其实很容易想明白。先把需要连的边多的节点连掉,后面整棵树连边才会更均匀,才能尽量拉近最远两点间的距离。
依据这个策略我们开始构造,这里我们用变量
容易发现连边复杂度为
附上代码:
#include<bits/stdc++.h>
#define int long long
#define il inline
#define pii pair<int,int>
#define mk make_pair
#define mod 100000000
using namespace std;
il int rd(){
int jya=0,tl=1;char jyt=getchar();
while(!isdigit(jyt)){if(jyt=='-')tl=-1;jyt=getchar();}
while(isdigit(jyt)){jya=(jya<<1)+(jya<<3)+(jyt-'0');jyt=getchar();}
return jya*tl;
}
il void wr(int jjy){
if(jjy<0)putchar('-'),jjy=-jjy;
if(jjy>9)wr(jjy/10);
putchar(jjy%10+48);
}
il int max(int x,int y){return x>=y?x:y;}
il int min(int x,int y){return x<=y?x:y;}
const int JYAAKIOI=1145141919810;
struct node{
int id,x;
}a[200086],b[200086];
int T,n,now;
vector<int>l,r;
il bool cmp(node x,node y){
return x.x>y.x;
}
signed main(){
//freopen("jytwcsnm.in","r",stdin);
//freopen("jytwcsnm.out","w",stdout);
T=rd();
while(T--){
l.clear();r.clear();
n=rd();
for(int i=1;i<=n;++i)a[i].x=rd(),a[i].id=i;
sort(a+1,a+1+n,cmp);
now=2;
for(int i=1;i<=n;++i){
for(int j=1;j<=a[i].x;++j){
l.push_back(a[i].id);
r.push_back(a[now].id);
--a[now].x;
++now;
}
}
for(int i=0;i<l.size();++i){
wr(l[i]),putchar(' '),wr(r[i]),putchar('\n');
}
}
return 0;
}