Codeforces 1082D Maximum Diameter Graph(贪心构造)
题意
给n个点,每个点有连线度数上限,要求使得建立的无向联通图直径最长。
思路
直接贪心,把所有的度数大于1的点连成一条线,再把度数为1的点往上插就可以了,插不下就输出不行。
这么简单的题,题解都不用看几分钟就敲出来了,只能说当时以为自己退役了心情低落,说着佛系打CF结果真的佛系掉分了。
代码
#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
struct edge{
int from;
int to;
int nxt;
edge(int f,int t,int n):from(f),to(t),nxt(n){}
};
int egs[505];
vector<edge> edges;
void addedge(int f,int t){
edges.emplace_back(f,t,egs[f]);
egs[f]=edges.size()-1;
}
struct node
{
int ind;
int degree;
}a[505];
bool cmp(node aa,node bb){
if(aa.degree!=bb.degree)
return aa.degree>bb.degree;
else
return aa.ind<bb.ind;
}
int main() {
int n;
cin>>n;
memset(egs,-1,sizeof egs);
int counterone=0;
int counternotone=0;
for(int i=1;i<=n;i++){
cin>>a[i].degree;
if(a[i].degree>1){
counternotone++;
}
else{
counterone++;
}
a[i].ind=i;
}
sort(a+1,a+n+1,cmp);//按度数排序
bool degreeone=false;
bool imp=false;
int endone=n;
for(int i=2;i<=n;i++){
if(!degreeone){
addedge(a[i-1].ind,a[i].ind);
if(a[i].degree==1){
degreeone=true;//后面的点都是1了,但是第一个1的点先和最右边的点连,还算直径的
endone=i;
}
a[i-1].degree--;
a[i].degree--;
if(a[i-1].degree<0 || a[i].degree<0){
imp=true;
break;
}
}
else{
bool succeeded=false;
for(int j=1;j<endone;j++){//从最左边开始,见到空位就插。
if(a[j].degree>=1){
addedge(a[j].ind,a[i].ind);
a[j].degree--;
a[i].degree--;
succeeded=true;
break;
}
}
if(!succeeded){
imp=true;//找不到能插点的地方,那就不可能
break;
}
}
}
if(imp){
cout<<"NO"<<endl;
}
else{
if(counterone>=2){
counternotone+=2;//度数为1的点最多有两个能加入直径。
}
else{
counternotone+=counterone;
}
cout<<"YES "<<counternotone-1<<endl;
cout<<edges.size()<<endl;
for(int i=0;i<edges.size();i++){
cout<<edges[i].from<<" "<<edges[i].to<<endl;
}
}
return 0;
}
纯粹自己想出来的