题目链接
Counting Cliques
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1371 Accepted Submission(s): 527
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
题解:
因为数据量比较小,直接爆搜就可以了,不过有一点要注意,爆搜时用一个数组记录在完全图里面的点,而且为了保证不重复,这些点按照递增排列,那么对于边u-v(u<v)此时图就只需要存u->v就行了,不然会T。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const int inf=0x3fffffff;
const ll mod=1000000007;
const int maxn=100+10;
int g[maxn][maxn];
int head[maxn];
struct edge
{
int from,to,next;
}e[maxn*20]; //
int tol=0;
void add(int u,int v)
{
e[++tol].to=v,e[tol].next=head[u],head[u]=tol;
}
void init()
{
memset(head,0,sizeof(head));
memset(g,0,sizeof(g));
tol=0;
}
int ans;
int n,m,s;
void dfs(int u,int sz,int *tmp)
{
if(sz==s)
{
ans++;
return;
}
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
//if(v<u) continue;
bool flag=true;
for(int j=1;j<=sz;j++)
{
if(!g[tmp[j]][v])
{
flag=false;
break;
}
}
if(flag)
{
tmp[sz+1]=v;
dfs(v,sz+1,tmp);
}
}
}
int main()
{
int cas;
scanf("%d",&cas);
while(cas--)
{
scanf("%d%d%d",&n,&m,&s);
init();
while(m--)
{
int a,b;
scanf("%d%d",&a,&b);
g[a][b]=g[b][a]=1;
if(a>b) swap(a,b);
add(a,b); //只保存每个点比他大的相邻点
//add(b,a);
}
ans=0;
for(int i=1;i<=n;i++)
{
int tmp[maxn];
memset(tmp,0,sizeof(tmp));
tmp[1]=i;
dfs(i,1,tmp);
}
printf("%d\n",ans);
}
return 0;
}
本文介绍了一个计数特定大小完全子图的问题,并提供了一种适用于小规模数据集的解决方案。通过深度优先搜索(DFS)遍历图的所有可能组合来找出所有指定大小的完全子图(clique),并分享了代码实现细节。
586

被折叠的 条评论
为什么被折叠?



