Uva 315 求无向图的割点的个数

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=251

A Telephone Line Company (TLC) is establishing a new telephone cable network. They are connecting several places numbered by integers from 1 to N. No two places have the same number. The lines are bidirectional
and always connect together two places and in each place the lines end in a telephone exchange. There is one telephone exchange in each place. From each place it is possible to reach through lines every other place, however it need not be a direct connection,
it can go through several exchanges. From time to time the power supply fails at a place and then the exchange does not operate. The officials from TLC realized that in such a case it can happen that besides the fact that the place with the failure is unreachable,
this can also cause that some other places cannot connect to each other. In such a case we will say the place (where the failure occured) is critical. Now the officials are trying to write a program for finding the number of all such critical places. Help
them.

Input

The input file consists of several blocks of lines. Each block describes one network. In the first line of each block there is the number of places N < 100. Each of the next at most N lines contains
the number of a place followed by the numbers of some places to which there is a direct line from this place. These at mostN lines completely describe the network, i.e., each direct connection of two places in the network is contained at least in
one row. All numbers in one line are separated by one space. Each block ends with a line containing just 0. The last block has only one line with N = 0.

Output

The output contains for each block except the last in the input file one line containing the number of critical places.

Sample Input

5
5 1 2 3 4
0
6
2 1 3
5 4 6 2
0
0

Sample Output

1
2
/**
uva315 求无向图的割点的个数
解题思路:利用tarjan算法求无向图的割点(套用求割点,桥的模板)
*/
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn=10010;
const int maxm=100010;

struct note
{
    int v,next;
    bool cut;
}edge[maxm];

int head[maxn],ip;

void init()
{
    memset(head,-1,sizeof(head));
    ip=0;
}

int low[maxn],dfn[maxn],st[maxn],dex,top;
bool in_st[maxn],cut[maxn];
int add_block[maxn];
int bridge;
int n;

void addedge(int u,int v)
{
    edge[ip].v=v,edge[ip].next=head[u],head[u]=ip++;
}

void tarjan(int u,int pre)
{
    low[u]=dfn[u]=++dex;
    st[top++]=u;
    in_st[u]=true;
    int son=0;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(v==pre)continue;
        if(!dfn[v])
        {
            son++;
            tarjan(v,u);
            if(low[u]>low[v])low[u]=low[v];
            ///桥
            if(low[v]>dfn[u])
            {
                bridge++;
                edge[i].cut=true;
                edge[i^1].cut=true;
            }
            ///割点
            if(u!=pre&&low[v]>=dfn[u])
            {
                cut[u]=true;
                add_block[u]++;
            }
        }
        else if(low[u]>dfn[v])
            low[u]=dfn[v];
    }
    ///树根,需满足条件分支数大于1
    if(u==pre&&son>1)cut[u]=true;
    if(u==pre)add_block[u]=son-1;
    in_st[u]=false;
    top--;
}

void solve()
{
    memset(dfn,0,sizeof(dfn));
    memset(in_st,false,sizeof(in_st));
    memset(add_block,0,sizeof(add_block));
    memset(cut,false,sizeof(cut));
    dex=top=0;
    bridge=0;
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i])
            tarjan(i,i);
    }
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        if(cut[i])
            ans++;
    }
    printf("%d\n",ans);
}
int g[110][110];
char buf[1010];
int main()
{
    while(~scanf("%d",&n))
    {
        if(n==0)break;
        gets(buf);
        memset(g,0,sizeof(g));
        while(gets(buf))
        {
            if(strcmp(buf,"0")==0)break;
            char *p=strtok(buf," ");
            int u;
            sscanf(p,"%d",&u);
            p=strtok(NULL," ");
            int v;
            while(p)
            {
                sscanf(p,"%d",&v);
                p=strtok(NULL," ");
                g[u][v]=g[v][u]=1;
            }
        }
        init();
        for(int i=1;i<=n;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                if(g[i][j])
                {
                    addedge(i,j);
                    addedge(j,i);
                }
            }
        }
        solve();
    }
    return 0;
}
时间: 2024-08-24 20:45:33

Uva 315 求无向图的割点的个数的相关文章

求无向图的割点和桥

/** * 求 无向图的割点和桥 * 可以找出割点和桥,求删掉每个点后增加的连通块. * 需要注意重边的处理,可以先用矩阵存,再转邻接表,或者进行判重 * 调用solve输出割点数,全局变量bridge记录边的个数 */ #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> using namespace std; const int maxn=1001

UVA 315 求割点数

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=251 测模版: #include <stdio.h> #include <iostream> #include <algorithm> #include <string.h> #include <queue> #includ

tarjan算法--求无向图的割点和桥

一.基本概念 1.桥:是存在于无向图中的这样的一条边,如果去掉这一条边,那么整张无向图会分为两部分,这样的一条边称为桥无向连通图中,如果删除某边后,图变成不连通,则称该边为桥. 2.割点:无向连通图中,如果删除某点后,图变成不连通,则称该点为割点. 二:tarjan算法在求桥和割点中的应用 1.割点:1)当前节点为树根的时候,条件是“要有多余一棵子树”(如果这有一颗子树,去掉这个点也没有影响,如果有两颗子树,去掉这点,两颗子树就不连通了.) 2)当前节点U不是树根的时候,条件是“low[v]>=

UVA 315 求连通图里的割点

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=20837 哎 大白书里求割点的模板不好用啊,许多细节理解起来也好烦..还好找了另一份模板 请注意,这道题里的每组数据都是只有一组连通图的 #include <iostream> #include <cstdio> #include <vector> #include <cstring> using namespace std; const

POJ 2117 求无向图的割点

Electricity Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4332   Accepted: 1419 Description Blackouts and Dark Nights (also known as ACM++) is a company that provides electricity. The company owns several power plants, each of them sup

求无向图的割点 (poj 1144 Network)

割点 :去掉该点后原来的图不连通(出现好几个连通分量),该点被称为割点. 注意删除某点意味着和该点关联的边也全部删除 求割点的伪代码 DFS(v1,father): dfn[v1] = low[v1] = ++dfsClock vis[v1] = true child = 0 for each egde(v1,v2) in E: if(vis[v2] == false) : //(v1,v2)是父子边 DFS(v2,v1) child++ low[v1] = Min(low[v1],low[v2

Tarjan求无向图割点、桥详解

tarjan算法--求无向图的割点和桥 一.基本概念 1.桥:是存在于无向图中的这样的一条边,如果去掉这一条边,那么整张无向图会分为两部分,这样的一条边称为桥无向连通图中,如果删除某边后,图变成不连通,则称该边为桥. 2.割点:无向连通图中,如果删除某点后,图变成不连通,则称该点为割点. 二:tarjan算法在求桥和割点中的应用 1.割点:1)当前节点为树根的时候,条件是"要有多余一棵子树"(如果这有一颗子树,去掉这个点也没有影响,如果有两颗子树,去掉这点,两颗子树就不连通了.) 2)

ZOJ 2588 Burning Bridges 求无向图桥 边双连通裸题

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1588 binshen的板子: #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #i

无向图求割点 UVA 315 Network

输入数据处理正确其余的就是套强联通的模板了 #include <iostream> #include <cstdlib> #include <cstdio> #include <algorithm> #include <vector> #include <queue> #include <cmath> #include <stack> #include <cstring> using namespa