1. 程式人生 > >2016ACM/ICPC亞洲區瀋陽站 Counting Cliques HDU

2016ACM/ICPC亞洲區瀋陽站 Counting Cliques HDU

  • 題意:給你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); } }