题意
给定一个n,n个节点的最大度,
问是否能构成一个无向连通图,
并求该图的最大直径(直径定义为直径上任意两点间的距离都是该图上的最短距离),
输出所有具体的图的构造边(u,v)中的u,v。
题解
只要能构成树就能满足上面的条件了,而且多余的边显然多余(有环的话拆环会使直径更大)。
对于能构成一棵树的情况,
对于度大于等于2的节点,连成一条链,
取两个度为1的点在链两头一边挂一个,
剩下的度为1的点挂在链上,
从而保证链最长。
思路来源
张舟亢学长&&马石页老师
心得
感觉自己真的好菜啊
没排序+break,C题被hack成TLE了
没加break自己还Debug不出,GG
最后还是马石页老师一发入魂
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <functional>
const int INF=0x3f3f3f3f;
const int maxn=500+10;
const int mod=1e9+7;
const int MOD=998244353;
const double eps=1e-7;
typedef long long ll;
#define vi vector<int>
#define si set<int>
#define pii pair<int,int>
#define pi acos(-1.0)
#define pb push_back
#define mp make_pair
#define lowbit(x) (x&(-x))
#define sci(x) scanf("%d",&(x))
#define scll(x) scanf("%lld",&(x))
#define sclf(x) scanf("%lf",&(x))
#define pri(x) printf("%d",(x))
#define rep(i,j,k) for(int i=j;i<=k;++i)
#define per(i,j,k) for(int i=j;i>=k;--i)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
int n,sum,len,pos;
struct node
{
int degree;
int id;
}q[maxn];
bool cmp(node a,node b)
{
if(a.degree!=b.degree)return a.degree<b.degree;
else return a.id<b.id;
}
vector<pii>ans;
//先连成链 再挂度为1的点
int main()
{
sci(n);
rep(i,0,n-1)
{
sci(q[i].degree);
q[i].id=i;
sum+=q[i].degree;
}
if(sum<2*(n-1))return puts("NO"),0;
sort(q,q+n,cmp);
rep(i,0,n-1)
{
if(q[i].degree>=2)
{
pos=i;
break;
}
}
rep(i,pos,n-2)//先成链
{
ans.push_back(pii(q[i].id,q[i+1].id));
q[i].degree--,q[i+1].degree--;
}
len=n-1-pos;
rep(i,0,pos-1)
{
if(!i)//挂头
{
ans.push_back(pii(q[0].id,q[pos].id));
q[0].degree--,q[pos].degree--;
len++;
}
else if(i==1)//挂尾
{
ans.push_back(pii(q[1].id,q[n-1].id));
q[1].degree--,q[n-1].degree--;
len++;
}
else
{
rep(j,pos,n-1)//把剩下的点挂上
{
if(!q[j].degree)continue;
ans.push_back(pii(q[i].id,q[j].id));
q[i].degree--,q[j].degree--;
break;//i挂到j上,i就不能挂在别的上了啊QAQ 忘了breakWA好多发
}
}
}
printf("%s %d\n","YES",len);
int num=ans.size();
printf("%d\n",n-1);
rep(i,0,num-1)
{
int u=ans[i].first,v=ans[i].second;
if(u>v)swap(u,v);
printf("%d %d\n",1+u,1+v);
}
return 0;
}