博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
P3388 【模板】割点(割顶)
阅读量:5103 次
发布时间:2019-06-13

本文共 3384 字,大约阅读时间需要 11 分钟。

题目背景

割点

题目描述

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

输入输出格式

输入格式:

 

第一行输入n,m

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

 

输出格式:

 

第一行输出割点个数

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

 

输入输出样例

输入样例#1:
6 71 21 31 42 53 54 55 6
输出样例#1:
1 5

说明

n,m均为100000

tarjan 图不一定联通!!!

 

割点真是一个非常神奇的东西。

虽然和tarjan很像,

而且能理解其中的奥秘。

但是代码还是看的一脸蒙蔽,。

1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #define lli long long int 9 using namespace std;10 const int MAXN=1000001;11 const int maxn=0x7fffff;12 inline void read(int &n)13 {14 char c='+';int x=0;bool flag=0;15 while(c<'0'||c>'9')16 {c=getchar();if(c=='-')flag=1;}17 while(c>='0'&&c<='9')18 {x=(x<<1)+(x<<3)+c-48;c=getchar();}19 flag==1?n=-x:n=x;20 }21 int n,m;22 struct node23 {24 int u,v,nxt;25 }edge[MAXN];26 int head[MAXN];27 int num=1;28 void add_edge(int x,int y)29 {30 edge[num].u=x;31 edge[num].v=y;32 edge[num].nxt=head[x];33 head[x]=num++;34 }35 int dfn[MAXN];//dfs的顺序36 int low[MAXN];// 每个点能追溯到的最近公共祖先37 int vis[MAXN];38 int ans[MAXN];// 是否是割点 39 int ansnum; //割点的数量 40 int tot=0;41 int tarjan(int now,int fa)42 {43 dfn[now]=low[now]=++tot; 44 int ch=0;45 for(int i=head[now];i!=-1;i=edge[i].nxt)46 {47 if(low[edge[i].v]!=0)48 low[edge[i].u]=min(low[edge[i].u],dfn[edge[i].v]);49 else 50 if(low[edge[i].v]==0)51 {52 ch++;//孩子的数量53 int nxt=tarjan(edge[i].v,edge[i].u);54 low[edge[i].u]=min(low[edge[i].u],low[edge[i].v]);55 if((fa==-1&&ch>1)||(fa!=-1&&dfn[edge[i].u]==low[edge[i].v]))56 {57 if(!ans[edge[i].u])58 {59 ans[edge[i].u]=1;60 ansnum++;61 }62 }63 }64 }65 return low[now];66 }67 int main()68 {69 read(n);read(m);70 memset(head,-1,sizeof(head));71 for(int i=1;i<=m;i++)72 {73 int x,y;74 read(x);read(y);75 add_edge(x,y);76 add_edge(y,x);77 }78 for(int i=1;i<=n;i++)79 if(low[i]==0)80 tarjan(i,-1); 81 printf("%d\n",ansnum);82 for(int i=1;i<=n;i++)83 if(ans[i]==1)84 printf("%d ",i);85 return 0;86 }

 

 

update in 2017.11.7

补一份利用void类型实现的代码

 

#include
#include
#include
#include
#include
using namespace std;const int MAXN=1e6+10;inline int read(){ char c=getchar();int f=1,x=0; while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();} while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();return x*f;}struct node{ int u,v,nxt;}edge[MAXN];int head[MAXN];int num=1;inline void add_edge(int x,int y){ edge[num].u=x; edge[num].v=y; edge[num].nxt=head[x]; head[x]=num++;}int dfn[MAXN];//询问的时间 int low[MAXN];//最早能追溯到的祖先 int n,m,tot;//当前已经枚举了多少节点 int ans[MAXN];//是否是割点 int ansnum=0; void tarjan(int now,int fa){ dfn[now]=low[now]=++tot; int ch=0; for(int i=head[now];i!=-1;i=edge[i].nxt) { if(low[edge[i].v]!=0) low[now]=min(low[now],dfn[edge[i].v]); else if(low[edge[i].v]==0) { ch++; tarjan(edge[i].v,now); low[now]=min(low[now],low[edge[i].v]); if((fa==-1&&ch>1)||(fa!=-1&&(dfn[now]==low[edge[i].v]) ) ) //一个点是根节点&&孩子的数量>1 //或是这个点不是根节点且访问的点的祖先是它 if(ans[edge[i].u]==0) ans[edge[i].u]=1,ansnum++; } }}int main(){ memset(head,-1,sizeof(head)); n=read();m=read(); for(int i=1;i<=m;i++) { int x=read(),y=read(); add_edge(x,y); add_edge(y,x); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i,-1); printf("%d\n",ansnum); for(int i=1;i<=n;i++) if(ans[i]) printf("%d ",i); return 0;}

  

转载于:https://www.cnblogs.com/zwfymqz/p/7147772.html

你可能感兴趣的文章
博弈论 从懵逼到入门 详解
查看>>
永远的动漫,梦想在,就有远方
查看>>
springboot No Identifier specified for entity的解决办法
查看>>
【Luogu1303】【模板】A*B Problem
查看>>
慵懒中长大的人,只会挨生活留下的耳光
查看>>
HTML——校友会(bootstrap)
查看>>
【分布计算环境学习笔记】2 分布式系统中的面向对象技术
查看>>
Enable SSH Server
查看>>
如何终止线程的运行(C/C++)
查看>>
"远程桌面连接--“发生身份验证错误。要求的函数不受支持
查看>>
【BZOJ1565】 植物大战僵尸
查看>>
视频:"我是设计师"高清完整版Plus拍摄花絮
查看>>
sicp solutions
查看>>
VALSE2019总结(4)-主题报告
查看>>
浅谈 unix, linux, ios, android 区别和联系
查看>>
PhotoZoom放大图片,真的能无损吗?
查看>>
转载分享移动网站最佳实践
查看>>
spark--环境搭建--4.ZooKeeper345集群搭建
查看>>
Codeforces Round #426 (Div. 2) C. The Meaningless Game
查看>>
51nod 1428 活动安排问题 (贪心+优先队列)
查看>>