题目链接:https://vjudge.net/problem/UVALive-6907
题意: 给出一张图,判断这张图中有多少个哑铃,哑铃判断的条件是,对于一个连通图:如果找到一条边连接这两个点的个数相同的完全图,那么这个联通图是哑铃状的。输出哑铃的个数。
举几个例子:
A、B、C都是哑铃状的图;
思路:很简单的一道题,首先我们对一个联通块进行树上DFS,说白了是就是那个TarJan树,求出每个以某个节点为根的树的大小,这样DFS只有桥连接的两个点的size 是对的,碰巧,我们也是只需要这两个点的size。顺便我们来求出这个来联通块的边的个数。
那么我们再进行Tarjan找到桥,即u - - > v,我们只需要判断张图是否是完全图的就行了。、
#include<bits/stdc++.h> using namespace std; const int maxn = 115; int T, N, M; int ans = 0; struct Edge { int to, next; Edge(int to = 0, int next = 0): to(to), next(next) {} } E[10050]; int head[maxn], tot; 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++; } int pre[maxn], low[maxn], dfsclock; int sz[maxn], edg; int DFS(int u, int fa) { sz[u] = 1; int ret = 0; for(int k = head[u]; ~k; k = E[k].next) { ret += 1; int v = E[k].to; if(v == fa || sz[v]) continue; ret += DFS(v, u); sz[u] += sz[v]; } return ret; } bool Tarjan(int u, int fa) { pre[u] = low[u] = ++dfsclock; for(int k = head[u]; ~k; k = E[k].next) { int v = E[k].to; if(v == fa) continue; if(!pre[v]) { if(Tarjan(v, u)) return true; low[u] = min(low[u], low[v]); if(low[v] > pre[u]) { int sum = sz[v] * (sz[v] - 1) + 1; if(sum == edg) return true; } } else low[u] = min(low[u], pre[v]); } return false; } void TarjanInit() { for(int i = 1; i <= N; i++) pre[i] = sz[i] = 0; dfsclock = ans = 0; for(int i = 1; i <= N; i++) { if(!pre[i]) { edg = DFS(i, i); edg /= 2; if(Tarjan(i, i)) ans++; } } } int main () { int ic = 0; scanf("%d", &T); while(T--) { scanf("%d %d", &N, &M); initedge(); for(int i = 1; i <= M; i++) { int u, v; scanf("%d %d", &u, &v); addedge(u, v); addedge(v, u); } TarjanInit(); printf("Case #%d: %d ", ++ic, ans); } return 0; }