您的位置:首页 > 理论基础 > 计算机网络

Hdu 5952 Counting Cliques(2016沈阳网络赛)

2018-03-23 19:37 369 查看
点击打开链接
今天中午闲逛hzwer博客看到的一个题,开学断断续续的感冒整得我很难受...
题意:一个clique是指里面任意两个点之间都有边相连的图,给N个点M条边,求有多少个大小为S的clique。一开始读成了求联通块是什么鬼。。
那很显然要深搜,并在深搜的过程中要去check一下从后向前这么多个点是不是满足任意两个点都有边相连的。这段时间看了不少图论知识(忘得也好快)反正就是vector+map[][]这样的方式,然后本以为这样跑一遍就完事了,无向图对吧,看着数据这么小(我根本没有看时限)。。结果答案是不对的,譬如第一组样例是6,雾。。。
好吧这里要用到偏序问题(离散里的知识忘得更干净),既然是一个clique,那势必可以找出一条也是唯一一条形如k1<k2<k3<k4<ks这样的路径,因为很显然,如果在vector 加边时无序的话在搜索时从clique中的每个点进去是会重复的,想一想的确是显然的。所以就是从小到大加边呀,写就好了(我也不知道自己懂了没有,但就是这个意思)。图论真是奇妙
更:后来走下楼时想了想,这里的核心明明是因为避免重复,所以只建立单向边,并且从小的序号指向大的序号。偏序也是种解释方式。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<bitset>
#include<vector>
#include<algorithm>
#include<set>
#include<map>
using namespace std;
int n,m,t,s,cnt;
vector<int >G[105];
int ma[105][105],a[25];
void dfs(int k,int depth)
{
a[depth]=k;
if(depth==s)
{
cnt++;
return;
}
for(int i=0;i<G[k].size();i++)
{
int p=G[k][i];
bool ok=false;
for(int j=1;j<depth;j++)
{
if(!ma[p][a[j]])
{
ok=true;
break;
}
}
if(!ok)dfs(p,depth+1);
}
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&s);
int p,q;
memset(ma,0,sizeof(ma));
for(int i=1;i<=m;i++)
{
scanf("%d%d",&p,&q);
if(p<q) G[p].push_back(q);
else G[q].push_back(p);
ma[p][q]=ma[q][p]=1;
}
cnt=0;
for(int i=1;i<=n;i++)
{
dfs(i,1);
}
printf("%d\n",cnt);
for(int i=1;i<=n;i++)G[i].clear();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  搜索