poj1144
2016-07-19 21:20
204 查看
Poj 1144
描述
一个电话线公司(简称TLC)正在建立一个新的电话线缆网络。他们连接了若干个地点分别从1到N编号。没有两个地点有相同的号码。这些线是双向的并且能使两个地点保持通讯。每个地点的线都终结于电话交换机。每个地点都有一个电话交换机。从每个地点都能通过线缆到达其他任意的地点,然而它并不需要直接连接,它可以通过若干个交换机来到达目的地。有时候某个地点供电出问题时,交换机就会停止工作。TLC的工作人员意识到,除非这个地点是不可达的,否则这种情况就会发生,它还会导致一些其它的地点不能互相通讯。在这种情况下我们会称这个地点(错误发生的地方)为critical。现在工作人员想要写一个程序找到所有critical地点的数量。帮帮他们。
输入
输入文件包括若组测试数据。每一组是一个网络,每一组测试数据的第一行是地点的总数量N<100. 每个接下来最多N行包括一个数字表示一个地点和与它相连接的地点的数字。这些最多N行完全描述了整个网络,比如,网络中每个直接连接的两个地点被至少一行包括。一行内的所有数字都要用空格隔开。每组数据需要用单独的一个0结束。最后的块只有一行即N=0。
输出
输出除了最后一个组其他每一个组的critical地点的数量,每个块用一行输出。
样例输入:
5
5 1 2 3 4
0
6
2 1 3
5 4 6 2
0
0
样例输出
1
2
提示:
你需要确定每行的结束。为了方便判断,每行的结束都没有多余的空白
割点判定
对于DFS树根, 判断度数是否大于1
对于其他点u, 如果不是根的直接儿子, 且low[u] >= dfn[P[u]], 则它的父亲v=P[u]是割点
描述
一个电话线公司(简称TLC)正在建立一个新的电话线缆网络。他们连接了若干个地点分别从1到N编号。没有两个地点有相同的号码。这些线是双向的并且能使两个地点保持通讯。每个地点的线都终结于电话交换机。每个地点都有一个电话交换机。从每个地点都能通过线缆到达其他任意的地点,然而它并不需要直接连接,它可以通过若干个交换机来到达目的地。有时候某个地点供电出问题时,交换机就会停止工作。TLC的工作人员意识到,除非这个地点是不可达的,否则这种情况就会发生,它还会导致一些其它的地点不能互相通讯。在这种情况下我们会称这个地点(错误发生的地方)为critical。现在工作人员想要写一个程序找到所有critical地点的数量。帮帮他们。
输入
输入文件包括若组测试数据。每一组是一个网络,每一组测试数据的第一行是地点的总数量N<100. 每个接下来最多N行包括一个数字表示一个地点和与它相连接的地点的数字。这些最多N行完全描述了整个网络,比如,网络中每个直接连接的两个地点被至少一行包括。一行内的所有数字都要用空格隔开。每组数据需要用单独的一个0结束。最后的块只有一行即N=0。
输出
输出除了最后一个组其他每一个组的critical地点的数量,每个块用一行输出。
样例输入:
5
5 1 2 3 4
0
6
2 1 3
5 4 6 2
0
0
样例输出
1
2
提示:
你需要确定每行的结束。为了方便判断,每行的结束都没有多余的空白
割点判定
对于DFS树根, 判断度数是否大于1
对于其他点u, 如果不是根的直接儿子, 且low[u] >= dfn[P[u]], 则它的父亲v=P[u]是割点
#include<cstdio> #include<cstring> struct edge{int v,next;}e[20010]; int low[10010],dfn[10010],cut[10010],first[10010]; //cut 记录他是否是截点 int index,n,a,son,b,i,vi,en; //index 当作时间的计数器 ,n 点的个数,son 根节点的孩纸数量 void addedge(int a,int b){e[en].v=b;e[en].next=first[a];first[a]=en++;} //建立领接表 void clean() { memset(low,0,sizeof(low)); memset(dfn,0,sizeof(dfn)); memset(e,0,sizeof(e)); memset(cut,0,sizeof(cut)); memset(first,0,sizeof(first)); index=0;en=0;son=0; /*因为少清理了一组数据所以居然出现了一组有答案,一组没有,心好累 memset(first,0,sizeof(first)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(cut,0,sizeof(cut)); memset(e,0,sizeof(e)); en=0;index=0; index=0;*/ } void tarjan(int rt,int fa) { int son=0;//每个点单独计算自己的儿子 low[rt]=dfn[rt]=++index; for(i=first[rt];i;i=e[i].next) { vi=e[i].v;//相连的点 if(!dfn[vi])//如果还没有被发现过就递归 { tarjan(vi,rt);son++;//新发现一个儿子加起来 low[rt]=low[rt]<low[vi]?low[rt]:low[vi]; if((dfn[rt]<=low[vi]&&rt!=1)||(rt==1&&son>1))cut[rt]=1; //如果dfn【rt】《low【vi】说明vi后面不能回到rt的祖先,说明没有环, //如果把rt减掉 rt的祖先就和vi及其子树不联通,所以rt为截 9eb2 点 //我是以1为根节点,如果rt==1,那他是根节点,如果同时son》1,根节点 //且不止一个孩纸,应该就是截点了 } if(vi!=fa) {low[rt]=low[rt]<dfn[vi]?low[rt]:dfn[vi];} //返租边 这个是防止少解,重边?反正示例数据没有vi!=fa会少解 } } int out() { int t=0;//把点遍历一边,有标记为一的计数器加一 for(i=1;i<=n;i++) { if(cut[i]==1)t++; } printf("%d\n",t);//输出的函数好简单,相比之读入 } int main() { while(scanf("%d",&n)&&n) { clean(); while(scanf("%d",&a)&&a) { while(getchar()!='\n')//为什么这里不会把输入流里的东西拿走 ,还是确实拿走了? { scanf("%d",&b); addedge(a,b); addedge(b,a); } }//这东西确实抄的啦,完全不会啦 tarjan(1,1);//以1为根节点,他自己当父亲 out(); } return 0; }
相关文章推荐
- tarjan求割点
- 图论-割点数目
- 基于DFS求无向图的割点及桥(割边)算法总结 POJ_1144题解
- POJ 1144 / ZOJ 1311 : Network - 割点个数
- 无向图的割点(关节点)
- ACM学习-自己写割点
- poj 1523 SPF 求割点
- Network
- POJ 1144 Network
- 割点算法模板(Cut-vertex)
- poj_1144/uva_315/zoj_1311 Network(割點模板題)
- HDU 4587 Two Nodes、POJ 2375 Reliable Nets (Tarjan)
- 【研究总结】连通性问题
- 【图论算法及模版】割点,割边,强联通分量,点双联通分量,边双联通分量
- POJ 1523 SPF
- poj1144Network 无向图求割点Tarjan
- poj1523(割点)
- XDU 1278
- 割点
- poj1144 network