首页 > 其他分享 >LightOJ - 1063 Ant Hills(割点)

LightOJ - 1063 Ant Hills(割点)

时间:2023-04-07 11:32:30浏览次数:43  
标签:pre cnt int 1063 LightOJ bcc Ant ++ lowlink


题目大意:求无向图中,有多少个割点

解题思路:模版题了

#include <cstdio>
#include <cstring>
#include <vector>
#include <stack>
using namespace std;
#define max(a,b)((a)>(b)?(a):(b))
#define min(a,b)((a)<(b)?(a):(b))
const int MAXNODE = 10005;
const int MAXEDGE = 100010;
const int INF = 0x3f3f3f3f;

struct Edge{
    int v, id, next;
    bool bridge;
    Edge() {}
    Edge(int v, int id, int next): v(v), id(id), next(next), bridge(false){}
}E[MAXEDGE * 2], cut[MAXEDGE];

struct Node {
    int u, v;
    Node() {}
    Node(int u, int v): u(u), v(v) {}
};

//bcc表示的是一个bcc里面的点
vector<int> bcc[MAXNODE];
stack<Node> Stack;
//pre纪录的是时间戳,lowlink纪录的是该点及其该子孙节点所能返回的最早时间戳是多少,bccno纪录的是该点当前是属于哪个bcc的
int head[MAXNODE], pre[MAXNODE], lowlink[MAXNODE], bccno[MAXNODE];
int n, m, tot, bcc_cnt, dfs_clock, cut_cnt; 
bool iscut[MAXNODE];

void AddEdge(int u, int v, int id) {
    E[tot] = Edge(v, id, head[u]);
    head[u] = tot++;
    u = u ^ v; v = u ^ v; u = u ^ v;
    E[tot] = Edge(v, id, head[u]);
    head[u] = tot++;
}

void init() {
    scanf("%d%d", &n, &m);
    memset(head, -1, sizeof(head));
    tot = 0;
    int u, v;
    for (int i = 0; i < m; i++) {
        scanf("%d%d", &u, &v);
        AddEdge(u, v, 0);
    }
}

//点双连通
void dfs(int u, int fa) {
    pre[u] = lowlink[u] = ++dfs_clock;
    int child = 0;//纪录当前节点有多少个子节点
    for (int i = head[u]; ~i; i = E[i].next) {
        int v = E[i].v;
        if (!pre[v]) {
            Stack.push(Node(u, v));
            child++;
            dfs(v, u);
            lowlink[u] = min(lowlink[u], lowlink[v]);//更新
            //子节点最多返回到该点
            if (lowlink[v] >= pre[u]) {
                //该边为桥
                if (lowlink[v] > pre[u]) {
                    E[i].bridge = E[i ^ 1].bridge = true;
                    cut[cut_cnt++] = E[i];
                }
                iscut[u] = true;
                bcc_cnt++; bcc[bcc_cnt].clear();
                while (1) {
                    Node x = Stack.top(); Stack.pop();
                    if (bccno[x.u] != bcc_cnt) {
                        bcc[bcc_cnt].push_back(x.u);
                        bccno[x.u] = bcc_cnt;
                    }
                    if (bccno[x.v] != bcc_cnt) {
                        bcc[bcc_cnt].push_back(x.v);
                        bccno[x.v] = bcc_cnt;
                    }

                    if (x.u == u && x.v == v) break;
                }
            }
        }
        else if (v != fa && pre[v] < pre[u]) {//反向边
            Stack.push(Node(u, v));
            lowlink[u] = min(lowlink[u], pre[v]);
        }
    }
    //u是根结点,且只有一个孩子,那就不是割点了
    if (fa < 0 && child == 1) iscut[u] = 0;
}
/*
//边双连通
int belong[MAXNODE];
int Stack[MAXNODE];
void find_bcc(int u, int fa) {
    pre[u] = lowlink[u] = ++dfs_clock;
    Stack[++top] = u;

    for (int i = head[u]; ~i; i = E[i].next) {
        int v = E[i].v;
        if (!pre[v]) {
            find_bcc(v, u);
            lowlink[u] = min(lowlink[u], lowlink[v]);
            if (lowlink[v] > pre[u]) { 
                E[i].bridge = E[i ^ 1].bridge = true;
                cut[cut_cnt++] = E[i];

                bcc_cnt++;
                while (1) {
                    int x = Stack[top--];
                    belong[x] = bcc_cnt;
                    if (x == v) break;
                }
            }
        }
        else if (pre[v] < pre[u] && v != fa) lowlink[u] = min(lowlink[u], pre[v]);
    }
}
*/

void find_bcc() {
    memset(pre, 0, sizeof(pre));
    memset(iscut, 0, sizeof(iscut));
    memset(bccno, 0, sizeof(bccno));
    dfs_clock = bcc_cnt = cut_cnt = 0;
    for (int i = 1; i <= n; i++) 
        if (!pre[i]) dfs(i, -1);
}

int cas = 1;
void solve() {
    find_bcc();
    int ans = 0;
    for (int i = 1; i <= n; i++)
        if (iscut[i]) ans++;
    printf("Case %d: %d\n", cas++, ans);
}
int main() {
    int test;
    scanf("%d", &test);
    while (test--) {
        init();
        solve();
    }
    return 0;
}


标签:pre,cnt,int,1063,LightOJ,bcc,Ant,++,lowlink
From: https://blog.51cto.com/u_10970600/6175965

相关文章

  • LightOJ - 1041 Road Construction(最小生成树)
    题目大意:给你N条边,看能否形成最小生成树,如果存在,输出值,不存在,另外输出解题思路:模版题#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#include<map>#include<string>#include<iostream>usingnamespacestd;constintMAXNOD......
  • Semantic Kernel 知多少 | 开启面向AI编程新篇章
    引言在ChatGPT火热的当下,即使没有上手亲自体验,想必也对ChatGPT的强大略有耳闻。当一些人在对ChatGPT犹犹豫豫之时,一些敏锐的企业主和开发者们已经急不可耐的开展基于ChatGPT模型AI应用的落地探索。因此,可以明确预见的是,AI能力的集成将会是很多应用都将面临的第一事项,而拥有......
  • geant4基础操作
    geant4官网:Geant4(cern.ch)打开B1实例的方法:进入用户文件夹/geant4_workspace/B1/build右键点击在终端中打开输入cmake..进行编译以及生成配置文件(预编译)再输入make合并编译器生成的目标exampleB1可执行文件输入./exampleB1对可执行文件运行,生成可视化界面配置参数文......
  • glib GVariant 3
    GVariant*value1,*value2,*value3,*value4;value1=g_variant_new("y",200);value2=g_variant_new("b",TRUE);value3=g_variant_new("d",37.5);value4=g_variant_new("x",G_GINT64_CONSTANT(99887766554433......
  • glib GVariant 2
    #include<stdio.h>#include<glib.h>#include<stdlib.h>#include<string.h>intmain(void){g_autoptr(GVariant)sessions=NULL;sessions=g_variant_new_parsed("[('2',uint321000,'nidhoe......
  • glib GVariant
    GVariant*g_variant_new_boolean(gbooleanvalue){ gucharv=value; returng_variant_new_from_trusted(G_VARIANT_TYPE_BOOLEAN,&v,1);} typedefstruct_GVariantTypeGVariantType;/** *G_VARIANT_TYPE_BOOLEAN: * *Thetypeofavalueth......
  • A tutorial that will show you how to build an instant messaging app with Sinch.
     http://stackoverflow.com/questions/26247986/unsatisfiedlinkerror-couldnt-load-sinch-android-rtc-from-loader-dalvik-systemhttps://www.sinch.com/tutorials/android-messaging-tutorial-using-sinch-and-parse/https://github.com/sinch/android-messaging-tutorial......
  • c++ std::variant
    std::variant是c++17引入的一个类型,其作用类似于C语言中的Union,但是比Union的功能强大的多。C语言中一个联合体Union可以储存多种类型数据,但缺点有很多。比如:1没有可用的方法来判断Union中真实储存的类型,获取值时也是内存拷贝的结果,可能会存在问题。这就只能靠程序员人脑保证......
  • antd modal弹出框,渲染antv图表
    弹出框的图标渲染获取不到dom,所以不能直接渲染,需要先判断Modal弹出框dom节点加载完成后,才能开始渲染。。。。。快下班了,直接上全部代码,不解释了<template><a-modalv-model:visible="visible":destroyOnClose="true"title="评估全景"@ok="cancel"@ca......
  • 从ReentrantLock 看AQS源码
    ReentrantLock简介ReentrantLock意思为可重入锁,指的是一个线程能够对一个临界资源重复加锁ReentrantLock与Synchronized的区别ReentrantLock支持公平锁和非公平锁,ReentrantLock内部有一个抽象内部类Sync集成于AQS,并且ReentrantLock就是通过Sync的具体实现(FairSync,NonfairSy......