洛谷 P3388 【模板】割点(割顶)

P3388 【模板】割点(割顶)

题目背景

割点

题目描述

给出一个n个点,m条边的无向图,求图的割点。

输入输出格式

输入格式:

第一行输入n,m

下面m行每行输入x,y表示x到y有一条边

输出格式:

第一行输出割点个数

第二行按照节点编号从小到大输出节点,用空格隔开

输入输出样例

输入样例#1:

6 7
1 2
1 3
1 4
2 5
3 5
4 5
5 6

输出样例#1:

1
5

说明

n,m均为100000

tarjan 图不一定联通!!!、

没错我以前就是不会,不服bb别solo

#include<bits/stdc++.h>
using namespace std;
#define maxn 1000000
int n,m,x,y,tot,tim,dfn[maxn],low[maxn],head[maxn],ans;
int cut_edge[maxn],cut_point[maxn];
bool vis[maxn];
struct Edge{
    int next,to,from;
}edge[maxn];

void add(int x,int y)
{
    edge[tot].to=y;
    edge[tot].next=head[x];
    head[x]=tot;
    tot++;
}

void tarjan(int now,int pre)
{
    int sum=0;
    bool if_=false;
    vis[now]=true;
    dfn[now]=low[now]=++tim;
    for(int i=head[now];i!=-1;i=edge[i].next)
    {
        int v=edge[i].to;
        if((i^1)!=pre)
        {
            if(!vis[v])
            {
                sum++;
                tarjan(v,i);
                if(low[v]>dfn[now]) cut_edge[i/2]=1;
                if(low[v]>=dfn[now]) if_=true;
                low[now]=min(low[now],low[v]);
            }
            else low[now]=min(low[now],dfn[v]);
        }
    }
    if(pre==-1)
    {
        if(sum>1)
        cut_point[now]=1;
    }
    else if(if_==1) cut_point[now]=1;
    return ;
}
int main()
{
    scanf("%d%d",&n,&m);
    memset(head,-1,sizeof(head));
    for(int i=1;i<=m;i++)
        scanf("%d%d",&x,&y),add(x,y),add(y,x);
    for(int i=1;i<=n;i++)
        if(!vis[i]) tarjan(i,-1);
    for(int i=1;i<=n;i++)
        if(cut_point[i]) ans++;
    printf("%d\n",ans);
    for(int i=1;i<=n;i++) if(cut_point[i]) printf("%d ",i);
    return 0;
}
时间: 2024-12-10 10:33:15

洛谷 P3388 【模板】割点(割顶)的相关文章

【C++】最近公共祖先LCA(Tarjan离线算法)&amp;&amp; 洛谷P3379LCA模板

1.前言 首先我们介绍的算法是LCA问题中的离线算法-Tarjan算法,该算法采用DFS+并查集,再看此算法之前首先你得知道并查集(尽管我相信你如果知道这个的话肯定是知道并查集的),Tarjan算法的优点在于相对稳定,时间复杂度也比较居中,也很容易理解(个人认为). 2.思想 下面详细介绍一下Tarjan算法的思想: 1.任选一个点为根节点,从根节点开始. 2.遍历该点u所有子节点v,并标记这些子节点v已被访问过. 3.若是v还有子节点,返回2,否则下一步. 4.合并v到u上. 5.寻找与当前点

AC自动机(附洛谷P3769模板题)

首先,介绍一下AC自动机(Aho-Corasick automaton),是一种在一个文本串中寻找每一个已给出的模式串的高效算法. 在学习AC自动机之前,你需要先学习Trie树和KMP算法,因为AC自动机正式利用并结合了两者的思想. 说到实际的不同,其实AC自动机只是在Trie树上引入了一个类似KMP中next数组的东西叫做Fail指针. 对于每一个节点,Fail指针指向该节点所代表的字符串中,次长的.在Trie树中存在的后缀(因为最长的在Trie树种存在的后缀就是其本身)所代表的节点. 举例:

洛谷P3375 [模板]KMP字符串匹配

To 洛谷.3375 KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了. 输入输出格式 输入格式: 第一行为一个字符串,即为s1(仅包含大写字母) 第二行为一个字符串,即为s2(仅包含大写字母) 输出格式: 若干行,每行包含一个整数,表示s2在s1中出现的位置 接下来1行,包括length(s2)个整

洛谷.3803.[模板]多项式乘法(FFT)

题目链接:洛谷.LOJ. FFT相关:快速傅里叶变换(FFT)详解.FFT总结.从多项式乘法到快速傅里叶变换. #include <cmath> #include <cctype> #include <cstdio> #include <algorithm> #define gc() getchar() const int N=1e6+5; const double PI=acos(-1); int n,m; struct Complex { double

洛谷.1919.[模板]A乘B Problem升级版(FFT)

题目链接:洛谷.BZOJ2179 //将乘数拆成 a0*10^n + a1*10^(n-1) + ... + a_n-1的形式 //可以发现多项式乘法就模拟了竖式乘法 所以用FFT即可 注意处理进位 //n位*n位最多就只有2n位了 //论putchar的速度..还是快的 #include <cmath> #include <cstdio> #include <cctype> #include <algorithm> #define gc() getchar

洛谷P3388 【模板】割点(割顶)

表示割点模板很难理解....但是呢,可以将整个图用深搜来一步步递归.. dfn[x]<=low[tmp] && x!=mr的点就++:完毕....PS:小心第一个节点...可能是一个二叉树结构 #include<iostream> #include<cstdio> #include<cstring> #define maxn 200100 using namespace std; int p[maxn],h[maxn],v[maxn],dfn[ma

洛谷 P3388 【模板】割点

题目背景 割点 题目描述 给出一个n个点,m条边的无向图,求图的割点. 输入输出格式 输入格式: 第一行输入n,m 下面m行每行输入x,y表示x到y有一条边 输出格式: 第一行输出割点个数 第二行按照节点编号从小到大输出节点,用空格隔开 输入输出样例 输入样例#1: 6 7 1 2 1 3 1 4 2 5 3 5 4 5 5 6 输出样例#1: 1 5 说明 n,m均为100000 tarjan 图不一定联通!!! 屠龙宝刀点击就送 #include <algorithm> #include

洛谷P3388 【模板】割点

给出一个n个点,m条边的无向图,求图的割点. u是cut vertex的两个条件: 1.存在v使v及其所有后代没有反向边连回u的祖先 2.u是根且有两个以上子节点 dfs一遍 low[u]是u及其后代所能连回的最早祖先 没有dfn[v]就dfs(v),然后用low[v]更新low[u](v是u的后代) 否则v不是fa就用dfn[v]更新low[u](u可以连回v)[不能用low[v],因为low[v]包含v的后代能连回] #include <iostream> #include <cst

【洛谷P3388 割点】

题目描述 给出一个n个点,m条边的无向图,求图的割点. 输入格式: 第一行输入n,m 下面m行每行输入x,y表示x到y有一条边 输出格式: 第一行输出割点个数 第二行按照节点编号从小到大输出节点,用空格隔开 输入样例: 6 7 1 2 1 3 1 4 2 5 3 5 4 5 5 6 输出样例: 1 5 说明 n,m均为100000 tarjan 图不一定联通!!! 题解 裸的tarjan模板.一个点为割点:1.不为根节点且dfn[now]<=low[e[i].to]  2.为根节点且有超过两个子