当时写了个做法是先连一个dag,然后每次把可以反向的边反向,要求三元环个数只能增加,然后这东西过了
求证明正确性 & 复杂度,悬1关
int n,m;
int c[5005],sum;
int t[5005][5005];
void run(){
cin>>n>>m;
int mx=0;
if(n&1)mx=n*(n-1)*(n+1)/24;
else mx=n*(n-2)*(n+2)/24;
if(m>mx){
cout<<"No\n";
re;
}
cout<<"Yes\n";
rep(i,n)c[i]=n-i-1;
rep(i,n)rep(j,n)t[i][j]=i<j;
sum=0;
while(sum<m){
bool ok=0;
rep(i,n)for(int j=n-1;j>=0;j--){
if(t[i][j]&&c[i]-c[j]>=2&&c[i]-c[j]-1+sum<=m){
ok=1;
sum+=c[i]-c[j]-1;
c[i]--;
c[j]++;
t[i][j]=0;
t[j][i]=1;
}
}
if(m==sum)break;
assert(ok);
}
rept(i,1,n){
rep(j,i)cout<<t[i][j];
cout<<"\n";
}
}