2016ACM/ICPC亞洲區瀋陽站 Counting Cliques HDU
阿新 • • 發佈:2018-12-13
- 題意:給你n個點,m條雙向邊,和一個整數s,要你求出大小等於s的完全子圖的個數(完全子圖:圖中的任一點都和其他所有點相連)。
- 演算法:dfs
- 思路:
- 將點逐個放進一個集合,如果該點與集合中的任一點都相連,則該點與集合中的點能構成完全子圖,將該點放入集合中,否則不放入。(這樣會有重複)
- 將每條邊都設成從標號小的點到大的點的單向邊(這樣就不會算入重複的圖)
#include <bits/stdc++.h>
#define pi acos(-1);
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
const LL LL_INF = 0x3f3f3f3f3f3f3f3f;
const int maxn = 100 + 10;
const int mod = 1e9 + 7;
int n, m, s;
bool G[maxn][maxn];
int head[maxn], ecnt, st[15];
LL ans;
struct Edge
{
int to, next;
Edge (int _to=0, int _next=0) : to(_to), next(_next) {}
}edge[1010];
void add(int u, int v)
{
edge[ecnt] = Edge(v, head[u]);
head[u] = ecnt++;
}
bool check(int v, int sz)
{
for(int i=0; i<sz; i++){
if(!G[st[i]][v]) return false;
}
return true;
}
void dfs(int u, int sz)
{
st[ sz] = u;
if(sz == s-1) { ++ans; --sz; return; }
for(int v, i=head[u]; ~i; i=edge[i].next){
v = edge[i].to;
if(check(v, sz)) dfs(v, sz+1);
}
}
int main()
{
int T; scanf("%d", &T);
while(T--){
scanf("%d%d%d", &n, &m, &s);
memset(G, 0, sizeof(G));
memset(head, -1, sizeof(head));
ecnt = 0;
int u, v;
for(int i=0; i<m; i++){
scanf("%d%d", &u, &v);
if(u > v) swap(u, v);
G[u][v] = 1; add(u, v);
}
ans = 0;
for(int i=1; i<=n; i++){
dfs(i, 0);
}
printf("%lld\n", ans);
}
}