题目链接
一开始忘记输出有多少条边,WA了好几发都跑不过第一组测试样例,开始怀疑自己是不是读了道假题,然后在大佬们的帮助下,终于AC,好伤心……读假样例(一定是我太弱了)。
我的思想是采用了树链剖分的dfs()构造思想,可能是因为最近少用了树链剖分有些想念吧,我用dfs()去建边,在此之前先按照节点的度按照降序排列,并且如果最后存在个度为1的节点的话,我们先把它放到第一个上面去就行了。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 505;
int N, sum_ofdu, num;
bool vis[maxN];
struct node
{
int du, id;
node(int a=0, int b=0):du(a), id(b) {}
}a[maxN];
bool cmp(node e1, node e2) { return e1.du > e2.du; }
struct Eddge
{
int no, to;
Eddge(int a=0, int b=0):no(a), to(b) {}
}need[maxN];
int dfs(int u, int fa, int len)
{
if(fa == N) return len - 1;
if(fa != -1) need[++num] = Eddge(a[fa].id, a[u].id);
if(a[u].du <= 0 || a[u+1].du <= 0) return len;
vis[a[u+1].id] = true;
a[u].du--;
a[u+1].du--;
int ans = dfs(u+1, u, len+1);
for(int i=u+1; i<=N && a[u].du; i++)
{
if(!vis[a[i].id] && a[u].du && a[i].du)
{
a[u].du--;
a[i].du--;
vis[a[i].id] = true;
dfs(i, u, 0);
}
}
return ans;
}
int main()
{
while(scanf("%d", &N)!=EOF)
{
sum_ofdu = num = 0; memset(vis, false, sizeof(vis));
for(int i=1; i<=N; i++)
{
scanf("%d", &a[i].du);
a[i].id = i;
sum_ofdu += a[i].du;
}
if(sum_ofdu < 2*(N-1)) { printf("NO\n"); continue; }
sort(a+1, a+1+N, cmp);
int flag = 0;
if(a[1].du > 1 && a[N].du == 1)
{
a[1].du--; a[N].du--;
need[++num] = Eddge(a[1].id, a[N].id);
vis[a[1].id] = true;
vis[a[N].id] = true;
flag = 1;
}
vis[a[1].id] = true;
printf("YES %d\n", dfs(1, -1, 0)+flag);
printf("%d\n", num);
for(int i=1; i<=num; i++) printf("%d %d\n", need[i].no, need[i].to);
}
return 0;
}
/*
17
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 2
*/
最后放了组测试样例,答案是16条边……一开始一直会WA在这,后来发现是因为当时既然已经把最后一个节点处理掉了,就得把它丢掉了。