构造一个简单图,要求每个节点的度$ \le a_i$,并且图的直径最大。
构造过程分为两步:
最后的结果就是一棵树
所以要求
\[
\sum_{i=1}^{n}a_i \ge 2(n-1)
\]
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<cmath>
#include<map>
#include<istream>
#include<cassert>
#include<set>
#define DEBUG(x) cout<<#x<<" = "<<x<<endl
#define DEBUG2(x,y) cout<<#x<<" = "<<x<<" , "<<#y<<" = "<<y<<endl
using namespace std;
typedef long long ll;
const int MAXN=600;
int n;
int a[MAXN];
int main()
{
// freopen("in.txt","r",stdin);
cin>>n;
int sum=0;
vector<int>ones;
for(int ii=1;ii<=n ;ii++ ){
cin>>a[ii];
sum+=a[ii];
if(a[ii]==1){
ones.push_back(ii);
a[ii]=0;
}
}
if(sum<2*n-2){
cout<<"NO";
return 0;
}
int ans=n-ones.size()-1+min(2,(int)ones.size());
cout<<"YES "<<ans<<endl<<n-1<<endl;
int lst=-1;
if(!ones.empty()){
lst=ones.back();
ones.pop_back();
}
for(int ii=1;ii<=n ;ii++ ){
if(a[ii]>1){
if(lst!=-1){
a[ii]--,a[lst]--;
cout<<lst<<" "<<ii<<endl;
}
lst=ii;
}
}
for(int ii=n;ii>=1 ;ii-- ){
while (!ones.empty()&&a[ii]>0){
a[ii]--;
cout<<ones.back()<<" "<<ii<<endl;
ones.pop_back();
}
}
}
什么是构造(construct)?
这个构造问题的要求有以下三个:
满足要求的顺序很重要。第一个最严格,所以优先第一个条件,满足直径最大。这样一来问题就迎刃而解了。
https://codeforces.com/blog/entry/63544
Codeforces 1082D Maximum Diameter Graph
原文:https://www.cnblogs.com/MalcolmMeng/p/10964118.html