Educational Codeforces Round 55 (Rated for Div. 2) D.Maximum Diameter Graph

题意

给定一个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;
}

猜你喜欢

转载自blog.csdn.net/Code92007/article/details/84640408