【模板】割点(割顶)
2017-06-18 15:07
225 查看
题目背景
割点题目描述
给出一个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均为100000tarjan 图不一定联通!!!
思路
dfs求割点;在DFS搜索树,我们可以发现有两类节点可以成为割点:
对根节点u,若其有两棵或两棵以上的子树,则该根结点u为割点;
对非叶子节点u(非根节点),若其子树的节点均没有指向u的祖先节点的回边,说明删除u之后,根结点与u的子树的节点不再连通;则节点u为割点。
2即n->v边中low[v]>=dfn[u];
代码实现
#include<cstdio> #include<algorithm> using namespace std; const int maxn=3e5; inline int min_(int x,int y){return x<y?x:y;} int n,m; int a,b; int h[maxn],hs,et[maxn],en[maxn]; void add(int u,int v){ ++hs,et[hs]=v,en[hs]=h[u],h[u]=hs; ++hs,et[hs]=u,en[hs]=h[v],h[v]=hs; } int s[maxn],ss; int dfn[maxn],dfns,low[maxn],v[maxn]; void tarjan(int k,int f){ dfn[k]=low[k]=++dfns; for(int i=h[k];i;i=en[i]) if(et[i]!=f){ if(dfn[et[i]]){ low[k]=min_(low[k],dfn[et[i]]); } else{ tarjan(et[i],k); low[k]=min_(low[k],low[et[i]]); if(low[et[i]]>=dfn[k]) ++v[k]; } } if(f&&v[k]) s[++ss]=k; if(!f&&v[k]>1) s[++ss]=k; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d%d",&a,&b); add(a,b); } for(int i=1;i<=n;i++){ if(!dfn[i]){ dfns=0; tarjan(i,0); } } sort(s+1,s+ss+1); printf("%d\n",ss); for(int i=1;i<=ss;i++) printf("%d ",s[i]); putchar('\n'); return 0; }
感谢;
http://www.cnblogs.com/en-heng/p/4002658.html
助我一A;
相关文章推荐
- 洛谷P3388 【模板】割点(割顶)(Tarjan算法)
- 割点 洛谷P3388 【模板】割点(割顶) 学习板子
- 洛谷P3388 【模板】割点(割顶)(tarjan求割点)
- 无向图的割顶和桥,无向图的双连通分量入门详解及模板
- 【模板】无向图的割顶
- 洛谷P3388 【模板】割点(割顶)
- poj 1144 Network【无向图求割顶模板题】
- luogu P3388 【模板】割点(割顶)
- 无向图的割顶和桥(tarjan模板)
- (模板)割点(割顶)tarjan类算法
- 图论算法-Tarjan模板 【缩点;割顶;双连通分量】
- 洛谷3388 割点(割顶)模板
- 洛谷—— P3388 【模板】割点(割顶)
- 【模板】割点(割顶)
- poj1144(求割顶模板题)
- 图论模板 求割顶/判断二分图
- 洛谷3388 【模板】割点(割顶)
- P3388 【模板】割点(割顶)
- P3388 【模板】割点(割顶)
- 图论模板 求割顶/判断二分图