UVALive 6907 Body Building

题目链接: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\n", ++ic, ans);
    }
    return 0;
}

 

posted @ 2017-07-30 16:20  _Mickey  阅读(190)  评论(0编辑  收藏  举报