poj1144 求割点的个数(注意输入的格式)

描述

电话线公司(TLC)正在建立一个新的电话电缆网络。它们连接了几个从1到N的整数编号的位置。没有两个地方有相同的号码。线路是双向的,并且总是将两个地方连接在一起,并且在每个地方线路终止于电话交换机。每个地方都有一个电话交换机。它来自每个地方 
可以通过其他地方的线路到达,但它不需要是直接连接,它可以通过几个交换。电源有时会在一个地方发生故障,然后交换机无法运行。TLC的官员意识到,在这种情况下,除了失败的地方无法到达之外,还可能导致其他地方无法相互连接。在这种情况下,我们会说这个地方(
发生故障的地方 )是至关重要的。现在,官员正试图编写一个程序来查找所有这些关键位置的数量。帮助他们。

输入

输入文件由几个行块组成。每个块描述一个网络。在每个块的第一行中,存在N <100的位数。接下来最多N行中的每一行包含一个地点的数字,后面跟有来自该地方的直线的一些地方的数量。这些最多N行完全描述了网络,即,网络中两个位置的每个直接连接至少包含在一行中。一行中的所有数字
由一个空格分隔 。每个块以一条仅包含0的行结束。最后一个块只有一行,N = 0;

产量

输出包含除输入文件中的最后一个块之外的每个块,其中一行包含关键位置的数量。

样本输入

<span style="color:#000000">
5
5 1 2 3 4
0
6
2 1 3
5 4 6 2
0
0
</span>

样本输出

<span style="color:#000000">
1
2
</span>

 题意:

给你一个无向图,问你这个图中有多少个割点.不过该题的输入格式说的比较难懂.这里解释一下:每个实例第一行是N,表示节点数.接下来可能有最多N行描述边信息的.

        其中这N行每行都是这样的:每行第一个数表示该行的主顶点u,接着的所有数字表示副顶点v1,v2,v3…等.表示u与v1,u与v2,u与v3分别都有一条边.

        最后这个实例以一个0表示结束.

        当然所有实例之后还有一个0(N=0),表示输入结束.
代码如下:

//求无向图的割顶和桥

#include<cstdio>
#include<cstring>
#include<vector>
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
const int maxn=1000+10;
int n,m;
int dfs_clock;//时钟,每访问一个节点增1
vector<int> G[maxn];//G[i]表示i节点邻接的所有节点
int pre[maxn];//pre[i]表示i节点被第一次访问到的时间戳,若pre[i]==0表示i还未被访问
int low[maxn];//low[i]表示i节点及其后代能通过反向边连回的最早的祖先的pre值
bool iscut[maxn];//标记i节点是不是一个割点

//求出以u为根节点(u在DFS树中的父节点是fa)的树的所有割顶和桥
//初始调用为dfs(root,-1);
int dfs(int u,int fa)  //直接用模板就行了
{
    int lowu=pre[u]=++dfs_clock;
    int child=0;    //子节点数目
    for(int i=0; i<G[u].size(); i++)
    {
        int v=G[u][i];
        if(!pre[v])
        {
            child++;//未访问过的节点才能算是u的孩子
            int lowv=dfs(v,u);
            lowu=min(lowu,lowv);
            if(lowv>=pre[u])
            {
                iscut[u]=true;      //u点是割顶
              /*  if(lowv>pre[u])   //(u,v)边是桥
                    printf("边(%d, %d)是桥\n",u,v);*/
            }
        }
        else if(pre[v]<pre[u] && v!=fa)//v!=fa确保了(u,v)是从u到v的反向边
        {
            lowu=min(lowu,pre[v]);
        }
    }
    if(fa<0 && child==1 )
        iscut[u]=false;//u若是根且孩子数<=1,那u就不是割顶
    return low[u]=lowu;
}

int main()
{
    while(scanf("%d",&n)==1&&n)
    {
        dfs_clock=0;
        memset(pre,0,sizeof(pre));
        memset(iscut,0,sizeof(iscut));
        for(int i=1;i<=n;i++) G[i].clear();
        
        int a,b;
         while(scanf("%d",&a)&&a)
        {
            while(getchar()!='\n')
            {
                scanf("%d",&b);

               G[a].push_back(b);
                    G[b].push_back(a);
            }
        }


        dfs(1,-1);
        int ans=0;
        for(int i=1;i<=n;i++)if(iscut[i]==true)
          ans++;

          cout<<ans<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40859951/article/details/84971283