您的位置:首页 > 其它

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]是割点

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  割点