Instability
题意:给你一副图,求有多少个集合,满足集合中有一个大小至少为3的子集要么构成完全图,要么相互独立。这道题实话不会,补题发现是一个定理:Ramsey定理
这倒是让我想到了今年ccpc网赛的C题:Friend-Graph 貌似也是这个定理,不过我们当时用bitset过的,现在补题才发现新天地。
来简述那个实用定理吧:任意6个人中都满足存在3个人相互认识或互不认识。
这样当n大于等于6的时候只需求C(i,6)之和即可。当k=3、4、5的时候暴力判就行。
const int N=50+10;
int n,m,w[N][N];
bool ok3(int a,int b,int c)
{
if(w[a][b]&&w[a][c]&&w[b][c]) return true;
if(!w[a][b]&&!w[a][c]&&!w[b][c]) return true;
return false;
}
bool ok4(int a,int b,int c,int d)
{
if(ok3(a,b,c)||ok3(a,b,d)||ok3(a,c,d)||ok3(d,b,c)) return true;
return false;
}
bool ok5(int a,int b,int c,int d,int e)
{
if(ok4(a,b,c,d)||ok4(a,b,c,e)||ok4(a,b,e,d)||ok4(a,c,e,d)||ok4(e,b,c,d)) return true;
return false;
}
ll C[55][55];
void init()
{
memset(C,0,sizeof(C));
C[0][0]=1;
for(int i=1;i<=50;i++)
{
C[i][0]=1;
for(int j=1;j<=50;j++)
C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD;
}
}
int main()
{
int t;
scanf("%d",&t);
int t1=t;
init();
while(t--)
{
scanf("%d%d",&n,&m);
memset(w,0,sizeof(w));
int u,v;
for(int i=1; i<=m; i++)
{
scanf("%d%d",&u,&v);
w[u][v]=w[v][u]=1;
}
ll ans=0;
for(int i=1; i<=n; i++)
for(int j=i+1; j<=n; j++)
for(int k=j+1; k<=n; k++)
if(ok3(i,j,k)) ans++;
for(int i=1; i<=n; i++)
for(int j=i+1; j<=n; j++)
for(int k=j+1; k<=n; k++)
for(int k1=k+1; k1<=n; k1++)
if(ok4(i,j,k,k1)) ans++;
for(int i=1; i<=n; i++)
for(int j=i+1; j<=n; j++)
for(int k=j+1; k<=n; k++)
for(int k1=k+1; k1<=n; k1++)
for(int k2=k1+1; k2<=n; k2++)
if(ok5(i,j,k,k1,k2)) ans++;
for(int i=6; i<=n; i++)
ans=(ans+C[n][i])%MOD;
printf("Case #%d: %lld\n",t1-t,ans);
}
return 0;
}
Friend-Graph
给你一幅图,如果存在3个及以上的人互相认识或互不认识,那么输出bad...,反之输出good..ccpc的时候用的bitset,时间9s+,但我们知道了那个定理,就直接特判n>=6的时候,其他的暴力判即可,时间655ms。
const int N=50+10;
int n,w[6][6];
inline int sc()
{
char ch=getchar();
int sum=0;
while(!(ch>='0'&&ch<='9'))ch=getchar();
while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=getchar();
return sum;
}
bool ok(int a,int b,int c)
{
if(w[a][b]&&w[a][c]&&w[b][c]) return true;
if(!w[a][b]&&!w[a][c]&&!w[b][c]) return true;
return false;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
int x;
if(n>=6)
{
for(int i=1; i<=n; i++)
for(int j=1; j<=n-i; j++)
x=sc();
puts("Bad Team!");
}
else
{
memset(w,0,sizeof(w));
for(int i=1; i<=n; i++)
for(int j=1; j<=n-i; j++)
{
x=sc();
w[i][j+i]=w[j+i][i]=x;
}
int flag=0;
for(int i=1; i<=n&&!flag; i++)
for(int j=i+1; j<=n&&!flag; j++)
for(int k=j+1; k<=n&&!flag; k++)
if(ok(i,j,k)) flag=1;
if(flag) puts("Bad Team!");
else puts("Great Team!");
}
}
return 0;
}
bitset:
bitset <3010> s[3010],u;
inline bool sc(int &ret)
{
char c;
if(c=getchar(),c==EOF) return 0;
ret=(c-'0');
while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
return 1;
}
int main()
{
int T,n;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
s[i].reset();
}
for(int i=1; i<n; i++)
{
for(int j=1; j<=n-i; j++)
{
int x=0;
sc(x);
if(x)
{
s[i][i+j]=1;
s[i+j][i]=1;
}
}
}
bool ans=true;
for(int i=1; i<=n; i++)
{
for(int j=i+1; j<=n; j++)
{
if(s[i][j])
{
u=s[i]&s[j];
if(u.count()!=0)
{
ans=false;
break;
}
}
}
if(!ans) break;
}
for(int i=1; i<=n; i++)
{
for(int j=i+1; j<=n; j++)
{
if(!s[i][j])
{
u=s[i]|s[j];
if(u.count()!=n-2)
{
ans=false;
break;
}
}
}
if(!ans) break;
}
if(ans) printf("Great Team!\n");
else printf("Bad Team!\n");
}
return 0;
}