题目大意:给出n个点,m条无向边,让你计算这幅母图中有几个大小为s的完全图。
完全图的意思是任意一个点都和其他点直接相连,完全图的大小指的就是完全图点的个数。
思路:比较巧妙的构图方式。我们会很自然地想到用dfs来找环,然后记录路径,判断是否成完全图,但是由于题目给的是双向边,如果直接构图的话,就会导致出现很多没有必要的情况,重复计算,爆栈超时。
所以在建图的时候只建从小的点到大的点的单向边,然后对n个点从小到大进行dfs,这样可以既可以保证不会有遗留的情况,也不会重复计算(因为每次走都是从小的点走到大的点,由于是单向边,所以不会回头)。dfs记录路径后,每次放入一个点,把之前路径上的所有点和这个点比较一下,是否是可达的,如果是,则继续dfs下一层,如果不是,则代表这个点无法和路径上的点一起构成完全图,舍弃,找下一条路。
我存图的方式是链式前向星,这样可以减少遍历的次数,而判断完全图的方式是直接用邻接矩阵,节约时间。(也就是我存了两幅一样的图)。
反思:还是一道赛后猛如虎的题目啊,比赛的时候想到用单向边构图,但是当时以为单向边判不了完全图(a能到b,我怎么知道b能不能到a),然后就没想下去了,实际上和答案只差一点点了呀!!
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string.h>
#include<sstream>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<bitset>
#define CLR(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
inline int rd(void) {
int x=0; int f=1;char s=getchar();
while(s<'0'||s>'9') { if(s=='-')f=-1; s=getchar();}
while(s>='0'&&s<='9') { x=x*10+s-'0';s=getchar();}
x*=f;return x;
}
int n,m,s,ans;
int head[1010],tot,lu[20];
struct edge{
int v,Next;
}edge[1010];
int mp[110][110];
void init(){
CLR(head,-1);
tot=0;
ans=0;
CLR(mp,0);
}
void addv(int u,int v){
edge[++tot].v=v;
edge[tot].Next=head[u];
head[u]=tot;
}
void dfs(int x,int deep){
if(deep==s){
ans++;
return;
}
lu[deep]=x;
for(int i=head[x];i!=-1;i=edge[i].Next){
int flag=1;
int v=edge[i].v;
for(int j=1;j<deep;j++){
if(mp[lu[j]][v]==0){
flag=0;
break;
}
}
if(flag){
dfs(v,deep+1);
}
}
return ;
}
int main(){
int T;
cin>>T;
while(T--){
scanf("%d%d%d",&n,&m,&s);
init();
int a,b;
for(int i=1;i<=m;i++){
scanf("%d%d",&a,&b);
if(a>b)swap(a,b);
mp[a][b]=1;
addv(a,b);
}
for(int i=1;i<=n;i++){
dfs(i,1);
}
printf("%d
",ans);
}
}
Counting Cliques
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 3880 Accepted Submission(s): 1387
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