Problem Description
A clique is a complete graph, in which there is an edge between every pair of the vertices. Given a graph with N vertices and M edges, your task is to count the number of cliques with a specific size S in the graph.
Input
The first line is the number of test cases. For each test case, the first line contains 3 integers N,M and S (N ≤ 100,M ≤ 1000,2 ≤ S ≤ 10), each of the following M lines contains 2 integers u and v (1 ≤ u < v ≤ N), which means there is an edge between vertices u and v. It is guaranteed that the maximum degree of the vertices is no larger than 20.
Output
For each test case, output the number of cliques with size S in the graph.
Sample Input
3 4 3 2 1 2 2 3 3 4 5 9 3 1 3 1 4 1 5 2 3 2 4 2 5 3 4 3 5 4 5 6 15 4 1 2 1 3 1 4 1 5 1 6 2 3 2 4 2 5 2 6 3 4 3 5 3 6 4 5 4 6 5 6
Sample Output
3 7 15
因为度为20,我们可以枚举团中编号最小的那个点,假设度为x,然后C(s-1,x)选出剩下s-1个点,判断是否为团即可
判断的时候可以压位来加速
重现赛的时候一开始时限1S,完全跑不过去,后来改成4S的时候拿了一血
#include<map>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct line
{
int s,t;
int next;
}a[2001];
int head[101];
int edge;
inline void add(int s,int t)
{
a[edge].next=head[s];
head[s]=edge;
a[edge].s=s;
a[edge].t=t;
}
int s,tot,p;
int vx[101];
int mp[101][101];
long long mx[101][2];
long long px[52];
inline void prepare()
{
int i;
px[1]=1;
for(i=2;i<=51;i++)
px[i]=px[i-1]*2ll;
}
//map<pair<long long,long long>,int> M;
long long ans;
int q[101];
inline void dfs(int d,int sx)
{
if(sx==s)
{
long long m1=0,m2=0;
int i;
for(i=1;i<=tot;i++)
{
if(q[i]<=50)
m1=(m1|px[50+1-q[i]]);
else
m2=(m2|px[100+1-q[i]]);
}
long long mm1=px[51]-1ll,mm2=px[51]-1ll;
for(i=1;i<=tot;i++)
{
mm1=(mm1&mx[q[i]][0]);
mm2=(mm2&mx[q[i]][1]);
}
if((m1&mm1)==m1&&(m2&mm2)==m2)
{
// M[make_pair(m1,m2)]++;
// if(M[make_pair(m1,m2)]==1)
ans++;
}
return ;
}
if(d==p+1)
return ;
tot++;
q[tot]=vx[d];
dfs(d+1,sx+1);
tot--;
dfs(d+1,sx);
}/*
inline void cale()
{
int i;
for(i=1;i<=s;i++)
q[i]=i;
while(q[1]==1)
{
long long m1=0,m2=0;
int i;
for(i=1;i<=s;i++)
{
if(vx[q[i]]<=50)
m1=(m1|px[50+1-vx[q[i]]]);
else
m2=(m2|px[100+1-vx[q[i]]]);
}
long long mm1=px[51]-1ll,mm2=px[51]-1ll;
for(i=1;i<=s;i++)
{
mm1=(mm1&mx[vx[q[i]]][0]);
mm2=(mm2&mx[vx[q[i]]][1]);
}
if((m1&mm1)==m1&&(m2&mm2)==m2)
ans++;
int j=s;
while(q[j]==p-(s-j))
j--;
q[j]++;
for(i=j+1;i<=s;i++)
q[i]=q[i-1]+1;
// for(i=1;i<=s;i++)
// printf("%d ",q[i]);
// printf("\n");
}
}*/
int main()
{
prepare();
int T;
scanf("%d",&T);
while(T>0)
{
T--;
ans=0;
//M.clear();
memset(head,0,sizeof(head));
edge=0;
int n,m;
scanf("%d%d%d",&n,&m,&s);
int i,j,u,v;
memset(mp,0,sizeof(mp));
for(i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
mp[u][v]=1;
mp[v][u]=1;
edge++;
add(u,v);
edge++;
add(v,u);
}
memset(mx,0,sizeof(mx));
for(i=1;i<=n;i++)
{
mp[i][i]=1;
for(j=1;j<=50;j++)
mx[i][0]=mx[i][0]*2ll+mp[i][j];
for(j=51;j<=n;j++)
mx[i][1]=mx[i][1]*2ll+mp[i][j];
}
for(i=1;i<=n;i++)
{
p=1;
vx[p]=i;
for(j=head[i];j!=0;j=a[j].next)
{
int t=a[j].t;
if(t<i)
continue;
p++;
vx[p]=t;
}
tot=1;
q[tot]=i;
dfs(2,1);
/* sort(vx+2,vx+1+p);
if(p>=s)
cale();*/
}
printf("%lld\n",ans);
}
return 0;
}