hdu 5952 Counting Cliques 2016ACM/ICPC沈阳赛区现场赛E

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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值