1. 程式人生 > >codeforces+D. Maximum Diameter Graph+給定 點的度數 構造(最大直徑樹)

codeforces+D. Maximum Diameter Graph+給定 點的度數 構造(最大直徑樹)

題目連結:http://codeforces.com/problemset/problem/1082/D
題目大意:
給你n個頂點
給定這n個頂點的的最大度數 ,讓你構造一棵樹,使得直徑最大。
如果不能構造樹,刪除NO,如果能,輸出YES 最大直徑,和每條邊
在這裡插入圖片描述
三個頂點:
度數最大為2,2,2
在這裡插入圖片描述

思路:
如果總度數>(n-1)*2則可以構造。
構造方法:把度數>1的頂點連成一條鏈,再把其餘的度數為1的比優先連線到鏈的起點和終點。再連線到其他點。

思考:第一次構造這種樹的題,也算是熟練了一下吧。

#include<bits/stdc++.h>
using namespace std;

int e[505];
vector<int> v;
vector<int> p;

int main()
{
    fill(e, e+505, 0);
    int n, x;
    cin>>n;
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&e[i]);
        ans+=e[i];
        if(e[i]!=1)
            v.push_back(i);/*度數為1的頂點*/
        else
            p.push_back(i);/*度數為1的頂點*/
    }
    if(ans<(n-1)*2)
    {
        cout<<"NO"<<endl;
    }
    else
    {
        int s=v.size()-1;
        s+=min(2, n-(const int)v.size());

        cout<<"YES"<<' '<<s<<endl;
        cout<<n-1<<endl;
        for(int i=0;i<v.size()-1;i++)/*把度數>1的頂點連成一條鏈*/
        {
            cout<<v[i]<<' '<<v[i+1]<<endl;
        }
		/*處理度數為1的點*/
        if(p.size()==1)
        {
            cout<<p[0]<<' '<<v[0]<<endl;
            p.erase(p.begin());
        }
        else if(p.size()>=2)
        {
            cout<<p[0]<<' '<<v[0]<<endl;
            cout<<p[1]<<' '<<v[v.size()-1]<<endl;
            p.erase(p.begin());
            p.erase(p.begin());
            while(p.size())
            {
                for(int i=0;i<v.size();i++)
                {
                    for(int j=e[v[i]];j>2;j--)
                    {
                        cout<<p[0]<<' '<<v[i]<<endl;
                        p.erase(p.begin());
                        if(p.size()==0)
                        {
                            return 0;
                        }
                    }
                }
            }
        }
    }

    return 0;
}