解题:USACO14MAR Counting Friends

题面

枚举每个数字是否能被删去,然后就是如何判定图是否存在。应该从按“度数”从大到小排序,从最大的顺次向其他点连边(先连“度数”小的可能会把一些可以和大“度数”点连接的点用掉)。但是这个排序每连一次都要做一次,而$N<=500$的情况下$O(n^3log$ $n)$并不能过。但是发现度数最多只有$n$,所以可以桶排,水过=。=

USACO官方题解说可以再套一个数据结构变成$O(n^2log$ $n)$,然而并不会做

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=505;
 6 int deg[N],bkt[N],mem[N];
 7 int tmp[N],outp[N];
 8 int n,p,cnt;
 9 int main ()
10 {
11     scanf("%d",&n);
12     register int i,j,k;
13     for(i=1;i<=n+1;i++)
14         scanf("%d",&deg[i]);
15     for(i=1;i<=n+1;i++)
16     {
17         bool flag=true;
18         for(j=1;j<=n+1;j++)
19             tmp[j]=(i==j)?0:deg[j];
20         for(j=1;j<=n+1;j++)
21         {
22               memset(bkt,0,sizeof bkt),p=0;
23             for(k=j+1;k<=n+1;k++) bkt[tmp[k]]++;
24             for(k=n;~k;k--) while(bkt[k]) mem[++p]=k,bkt[k]--;
25             for(k=1;k<=n-j+1;k++) tmp[j+k]=mem[k]; 
26             for(k=j+1;k<=n+1&&tmp[j];k++)
27                 if(tmp[k]) tmp[k]--,tmp[j]--;
28         }
29         for(j=1;j<=n+1;j++)
30             if(tmp[j]) {flag=false; break;}
31         if(flag) outp[++cnt]=i;
32     }
33     sort(outp+1,outp+1+cnt);
34     printf("%d
",cnt);
35     for(i=1;i<=cnt;i++)
36         printf("%d
",outp[i]);
37     return 0;
38 }
View Code
原文地址:https://www.cnblogs.com/ydnhaha/p/9678695.html