题目链接:【http://acm.hdu.edu.cn/showproblem.php?pid=5952】
题意:给出一张无向图,然后判断这张图中一共有多少个不同的大小为S的完全图,并且保证每个点的度不大于20。
题解:好吧,比赛的时候想太多了,结果时间刚不住,TTTT。正解其实很简单,就一个DFS。每次建立DFS(u),表示u在的大小为S的完全图个数,为了保证不重复,我们只建立单向边。每层DFS的时候,取一个点,当且仅的这个点与之前的所有点选过的点有边相连(神优化)。总复杂度是100 * 100 * (2 ^ 19) ,但是,应为边很少,所以,复杂度要少很多。
思维僵化啊。
#include<Bits/stdc++.h> using namespace std; const int maxn = 105; int T, N, M, S; struct Edge { int to, next; Edge() {} Edge(int to, int next): to(to), next(next) {} } E[2050]; int head[maxn], tot; int mp[maxn][maxn], vis[maxn], tmp[maxn]; int ans = 0; void initEdge() { for(int i = 0; i <= N; i++) head[i] = -1; tot = 0; } void addEdge(int u, int v) { E[tot] = Edge(v, head[u]); head[u] = tot++; } void DFS(int u, int pos) { if(pos == S) { ans++; return ; } for(int k = head[u]; ~k; k = E[k].next) { int v = E[k].to; bool fg = true; for(int i = 0; i < pos && fg; i++) if(!mp[v][tmp[i]]) fg = false; if(fg) { tmp[pos] = v; DFS(v, pos + 1); } } return ; } int main () { scanf("%d", &T); while(T--) { scanf("%d %d %d", &N, &M, &S); initEdge(); for(int i = 1; i <= N; i++) { vis[i] = 0; for(int j = i + 1; j <= N; j++) mp[i][j] = mp[j][i] = 0; } for(int i = 1; i <= M; i++) { int u, v; scanf("%d %d", &u, &v); addEdge(u, v); mp[u][v] = mp[v][u] = 1; } if(S == 2) { printf("%d\n", M); continue; } ans = 0; for(int i = 1; i <= N; i++) { tmp[0] = i; DFS(i, 1); } printf("%d\n", ans); } return 0; }
时间: 2024-11-05 20:28:18