hdu5952(暴搜+剪枝+铜牌题)

来源:互联网 发布:python pillow手册 编辑:程序博客网 时间:2024/04/27 13:51

Counting Cliques

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2956    Accepted Submission(s): 1072


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
34 3 21 22 33 45 9 31 31 41 52 32 42 53 43 54 56 15 41 21 31 41 51 62 32 42 52 63 43 53 64 54 65 6
 

Sample Output
3715
 

Source
2016ACM/ICPC亚洲区沈阳站-重现赛(感谢东北大学)
题意:n个点,m条边的无向图中,求点数为s的完全子图的数量。
思路:首先想到的肯定是建立一个无向边的图,进行暴力搜索每一个点即可,但是这样一来就会TLE。现在进行一些优化就是直接建立有向图,默认从低到高,因此只需要暴力搜索每一个点,将可能成为s元完全子图的点(这个点相连的所有点)也加入,同时更新这个完全子图中的点数和那些点,搜索到完全子图中点数为s返回即可。具体相应操作见代码中注释。
代码:
#include<bits/stdc++.h>using namespace std;typedef long long LL;const int maxn=1005;const int maxm=10005;int point[maxn],in[maxn];bool vis[maxn][maxn];int ans,n,m,s;vector<int>edge[maxm];void dfs(int u,int sum,int fa){    if(sum==s)//点数满足条件的完全图    {        ans++;        return;    }    if(in[u]<s-1) return;//如果某个点的入度小于s-1,这个点舍弃    for(int i=0;i<edge[u].size();i++)    {        int v=edge[u][i];        if(v==fa) continue;        bool flag=true;        for(int j=0;j<sum;j++)//判断这个点是否和当前图中其他点相互连通        {            if(vis[point[j]][v]==false)            {                flag=false;                break;            }        }        if(flag)        {            point[sum++]=v;//满足条件就加进当前图中继续搜索            dfs(v,sum,u);            sum--;        }    }}int main(){    int T;    scanf("%d",&T);    while(T--)    {        scanf("%d%d%d",&n,&m,&s);        for(int i=0;i<n;i++) edge[i].clear();        memset(in,0,sizeof(in));        memset(point,0,sizeof(point));        memset(vis,false,sizeof(vis));        for(int i=1;i<=m;i++)        {            int u,v;            scanf("%d%d",&u,&v);            if(u>v) swap(u,v);            in[u]++,in[v]++;            edge[u].push_back(v);            vis[u][v]=vis[v][u]=true;//标记哪些边出现        }        ans=0;        for(int i=1;i<=n;i++)//枚举这些点        {            point[0]=i;//记录点            dfs(i,1,-1);        }        printf("%d\n",ans);    }    return 0;}

原创粉丝点击