2021年度训练联盟热身训练赛第二场 F.Interstellar Love

  • 题意:给出一张图,求出该图有几个连通块(一个点不算一个连通块),并求出所有连通块中有几个连通块是存在环
  • 解析:求连通块用dfs或并查集均可做,这里主要是想记录一下怎么判断一个无向图中是否存在环(毕竟想了挺久)。主要思想还有通过dfs实现,不难发现,若一个无向图存在环(假设三个点a、b、c),在dfs搜索过程中,假设从a开始a -> b,b -> c若此时c -> a说明这三个点形成一个环,那此时的问题就是如何判断c是可以走到a,实际上:假若u -> v,若有一个结点x(x!=u),并且u曾经被访问过,说明该图中至少存在一个环
  • 代码:
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const int N = 1005;
vector<int> g[N];
int t, n, m, flag = 0;
int vis[N];
void dfs(int x, int pre)
{
    for(int i = 0; i < g[x].size(); i++)
    {
        int v = g[x][i];
        if(v == pre) continue; //除去上一个结点
        if(vis[v])
        {
            flag = 1; //除去上一个结点外仍访问到曾经访问到的结点,说明存在环
            continue;
        }
        vis[v] = 1;
        dfs(v, x);
    }
}
int main()
{
    cin >> t;
    for(int o = 1; o <= t; o++)
    {
        memset(vis, 0, sizeof vis);
        cin >> n >> m;
        for(int i = 1; i <= n; i++)
            g[i].clear();
        for(int i = 1; i <= m; i++)
        {
            int u, v;
            cin >> u >> v;
            g[u].push_back(v);
            g[v].push_back(u);
        }
        int cnt = 0, num = 0;
        for(int i = 1; i <= n; i++)
        {
            if(!vis[i])
            {
                if(!g[i].size()) continue; //一个点排除
                cnt ++;
                dfs(i, i);
                if(flag) num ++;
            }
            flag = 0;
        }
        printf("Night sky #%d: %d constellations, of which %d need to be fixed.\n\n", o, cnt, num);
    }
    return 0;
}


posted @ 2021-03-28 11:08  ~K2MnO4  阅读(87)  评论(0)    收藏  举报