兰道定理
定义竞赛图的比分序列是将竞赛图每个点的出度从小到大排列得到的序列。
所谓兰道定理,即一个长度为\(n\)的序列\(\{s_i\},s_i\le s_{i+1}\)是合法的比分序列当且仅当\(\forall k,\sum_{i=1}^ks_k\ge C(k,2)\)
进一步的一个竞赛图强连通的充要条件是:把它的所有顶点按照入度d从小到大排序,对于任意\(k\in [0,n-1]\)都不满足\(\sum_{i=1}^ks_i=C(i,2)\)
再进一步,可以通过此求出所有的强连通分量大小。
这道题是判断该序列是不是竞赛图的比分序列。
用上述结论即可。由于一场比赛两分故\(\forall k,\sum_{i=1}^ks_i\ge i(i-1)\)
注意\(\sum_{i=1}^ns_i=n(n-1)\)
考虑竞赛图特点必然存在一条哈密顿路径那么答案至少是\(n-1\)
若是答案为\(n\)则知每个点都要在强连通分量里\(\ge 3\)
使用兰道定理判断是否存在大小为\(1\)的强连通分量即可。
sc(n);
rep(1,n,i)
{
rep(1,n,j)
{
int x;
sc(x);
a[i]+=x;
}
}
sort(a+1,a+1+n);
int sum=0,w=0;
rep(1,n,i)
{
sum+=a[i];
if(sum==(i-1)*i/2)
{
if(i-w==1){put(n-1);return 0;}
w=i;
}
}
put(n);
Codeforces Round 432 (Div. 1)
还是兰道定理的应用利用背包来做。
即\(f_{i,j,k}\)表示表示到了第\(i\)个点度数用到了\(j\)总度数为\(k\)是否可行。
生成方案时可以考虑将最小度数点向其他较小度数点连边。剩余点向当前点连边。
这样竞赛图从\(n\)变为\(n-1\)由归纳知成立。
const int MAXN=20010,G=(mod+1)>>1;
int n,k,m,cnt,lim,B;
int a[MAXN],w[MAXN];
int f[66][32][4010],g[66][32][4010],p[66];
int b[66][66];
inline int cmp(int a,int b){return w[a]<w[b];}
signed main()
{
freopen("1.in","r",stdin);
sc(n);
rep(1,n,i)sc(a[i]);
sort(a+1,a+1+n);
f[0][0][0]=1;
rep(1,65,i)
{
rep(1,n,j)
{
rep((i-1)*(i-2)/2,3010,k)
{
if(f[i-1][j][k])
{
f[i][j][k+a[j]]|=f[i-1][j][k];
g[i][j][k+a[j]]=j;
}
if(f[i-1][j-1][k])
{
f[i][j][k+a[j]]|=f[i-1][j-1][k];
g[i][j][k+a[j]]=j-1;
}
}
}
}
int flag=0;
rep(n,65,i)if(f[i][n][(i-1)*i/2])
{
flag=i;break;
}
if(!flag){puts("=(");return 0;}
int cc=n,kk=flag,cnt=(kk-1)*kk/2;
while(flag)
{
p[flag]=flag;
w[flag]=a[cc];
cc=g[flag][cc][cnt];
cnt-=w[flag];
--flag;
}
cnt=kk;
while(cnt!=1)
{
int res=kk-cnt+1;
rep(res+1,res+w[p[res]],j)
b[p[res]][p[j]]=1;
rep(res+w[p[res]]+1,kk,j)
b[p[j]][p[res]]=1,--w[p[j]];
--cnt;
sort(p+kk-cnt+1,p+kk+1,cmp);
}
put(kk);
rep(1,kk,i){rep(1,kk,j)cout<<b[i][j];cout<<endl;}
//rep(1,kk,i)put(w[i]);
return 0;
}