https://www.luogu.com.cn/record/121247482
#include<bits/stdc++.h>
#define int long long
using namespace std;
namespace wxh666{
#define getchar getchar_unlocked
#define putchar putchar_unlocked
#define sqrt(a) __builtin_sqrt(a)
#define f(a,b,c) for(int a=b;a<=c;a++)
#define ff(a,b,c) for(int a=b;a>=c;a--)
#define max(x,y) (x>y?x:y)
#define min(x,y) (x<y?x:y)
template<typename T>
inline void read(T &ans)
{
char ch=getchar();int f=1;ans=0;
for(;!isdigit(ch);ch=getchar()) ch=='-'?f=-1:f=1;
for(;isdigit(ch);ch=getchar()) ans=(ans<<3)+(ans<<1)+(ch&15);
ans*=f;
return;
}
template<typename T,typename ...Args>
inline void read(T &tmp,Args &...tmps){read(tmp);read(tmps...);}
inline int read()
{
char ch=getchar();int f=1,ans=0;
for(;!isdigit(ch);ch=getchar()) ch=='-'?f=-1:f=1;
for(;isdigit(ch);ch=getchar()) ans=(ans<<3)+(ans<<1)+(ch&15);
return f*ans;
}
#define in read()
template<typename T>
inline void p(T x,bool g=0)
{
ios::sync_with_stdio(false);
cout<<x;
ios::sync_with_stdio(true);
return;
}
template<typename T>
inline void pk(T x,bool g=0)
{
ios::sync_with_stdio(false);
cout<<x<<" ";
ios::sync_with_stdio(true);
return;
}
template<typename T,typename ...Args>
inline void p(T x,Args ...xs){p(x);p(xs...);}
template<typename T,typename ...Args>
inline void pk(T x,Args ...xs){pk(x);pk(xs...);}
#define cs(dt,n,m) \
for(int i=1;i<=n;i++)\
{\
for(int j=1;j<=n;j++)\
printf("%d ",dt[i][j]);\
cout<<endl;\
}
};using namespace wxh666;
namespace lsq {
typedef int lsqxx;
struct lq {
struct lqbz {
lsqxx v,w,nxt;
}e[8000005];
lsqxx h[2005],cnt;
inline void add(lsqxx u,lsqxx v,lsqxx w=1) {
e[++cnt].v=v;
e[cnt].w=w;
e[cnt].nxt=h[u];
h[u]=cnt;
}
void erase() {cnt=0;memset(h,0,sizeof(h));return;}
#define F(z,u) for(int j=z.h[u],v=z.e[j].v,w=z.e[j].w;j;j=z.e[j].nxt,v=z.e[j].v,w=z.e[j].w)
}q;
};
using namespace lsq;
int n;
int dt[2005][2005],x;
int color[2005];
int a[2005],acnt;
void dfs(int u,int val)
{
a[acnt]+=(val<<1)-1;
color[u]=val;
F(q,u)
{
if(color[v]==val)
{
puts("No solution");
exit(0);
}
if(color[v]!=-1) continue;
dfs(v,val^1);
}
}
int dp[2005][4005];
#define dp(i,j) dp[i][j+2000]
signed main()
{
cin>>n;
f(i,1,n)
{
color[i]=-1;
while(true)
{
x=read();
if(!x) break;
dt[i][x]=1;
}
}
f(i,1,n) f(j,i+1,n) if((!dt[i][j])||(!dt[j][i])) q.add(i,j),q.add(j,i);
f(i,1,n) if(color[i]==-1) acnt++,dfs(i,1),a[acnt]=abs(a[acnt]);
dp(0,0)=1;
f(i,1,acnt)
f(j,-n,n)
dp(i,j)=dp(i-1,j-a[i])|dp(i-1,j+a[i]);
f(i,0,n)
{
// cout<<dp(n,i)<<endl;
if(dp(acnt,i))
{
pk(n/2-i+1,n/2+i,'\n');
return 0;
}
}
return 0;
}
/*
dp[i][j] 前i个块的集合点数差为j是否可以达到
*/