HDU-5952 爆搜DFS
HDU5952
题目大意
给一个\(n\)个点\(m\)条边的无向图,要求你选择其中\(s\)个点,使齐构成完全图,问满足要求的选法有几种。
\(N≤100\)
\(M≤1000\)
\(2≤S≤10\)
思路
数据范围那么小,显然是爆搜。
我们可以通过爆搜大小为s的团来得到答案,但是,普通爆搜肯定会TLE的
因为其中搜索了大量重复的团,例如:1-3-4-5其实和1-4-5-3是一样的
那么我们可以在搜索中保证团的大小一定是从小到大的,例如1-2-3-4 1-3-4-5
这样就避免了搜索重复的团
Code
#include<string>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define LL long long
#define MOD 998244353
#define PI 3.1415926535898
#define INF 0x3f3f3f3f
#define MAXN 300
const double EPS = 1e-8;
LL read()
{
LL x = 0, w = 1;
char ch = 0;
while (ch < '0' || ch>'9')
{
if (ch == '-')
{
w = -1;
}
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = x * 10 + ch - '0';
ch = getchar();
}
return w * x;
}
LL t, n, s, m, ui, vi, wi, ans;
LL mp[MAXN][MAXN], a[MAXN], as[MAXN][MAXN];
bool v[MAXN][MAXN], vis[MAXN];
LL head[MAXN], cnt = 0;
struct node
{
LL to, w, next;
};
node edge[20005];
inline void add(LL x, LL y, LL w)
{
edge[++cnt].to = y;
edge[cnt].next = head[x];
head[x] = cnt;
edge[cnt].w = w;
}
inline void init()
{
memset(edge, 0, sizeof(edge));
memset(a, 0, sizeof(a));
memset(mp, 0, sizeof(mp));
memset(head, 0, sizeof(head));
cnt = 0;
ans = 0;
}
LL dfs(LL x, LL cn)
{
LL sum = 0;
if (cn == s)
{
ans++;
v[x][cn] = 1;
as[x][cn] = 1;
return 1;
}
a[cn] = x;
for (register LL i = head[x]; i; i = edge[i].next)
{
bool f = 1;
for (register LL j = 1; j <= cn; j++)
{
if (mp[a[j]][edge[i].to] == 0)
{
f = 0;
break;
}
}
if (f)
{
dfs(edge[i].to, cn + 1);
}
}
return sum;
}
int main()
{
t = read();
while (t--)
{
init();
n = read();
m = read();
s = read();
for (register LL i = 1; i <= m; i++)
{
ui = read();
vi = read();
//wi = read();
if (ui > vi)
swap(ui, vi);
add(ui, vi, 1);
mp[ui][vi] = 1;
mp[vi][ui] = 1;
}
for (register LL i = 1; i <= n; i++)
{
dfs(i, 1);
}
cout << ans << endl;
}
return 0;
}