SPF POJ - 1523(tarjan求割点,求连通分量数)

Consider the two networks shown below. Assuming that data moves around these networks only between directly connected nodes on a peer-to-peer basis, a failure of a single node, 3, in the network on the left would prevent some of the still available nodes from communicating with each other. Nodes 1 and 2 could still communicate with each other as could nodes 4 and 5, but communication between any other pairs of nodes would no longer be possible.

Node 3 is therefore a Single Point of Failure (SPF) for this network. Strictly, an SPF will be defined as any node that, if unavailable, would prevent at least one pair of available nodes from being able to communicate on what was previously a fully connected network. Note that the network on the right has no such node; there is no SPF in the network. At least two machines must fail before there are any pairs of available nodes which cannot communicate.

Input
The input will contain the description of several networks. A network description will consist of pairs of integers, one pair per line, that identify connected nodes. Ordering of the pairs is irrelevant; 1 2 and 2 1 specify the same connection. All node numbers will range from 1 to 1000. A line containing a single zero ends the list of connected nodes. An empty network description flags the end of the input. Blank lines in the input file should be ignored.
Output
For each network in the input, you will output its number in the file, followed by a list of any SPF nodes that exist.

The first network in the file should be identified as “Network #1”, the second as “Network #2”, etc. For each SPF node, output a line, formatted as shown in the examples below, that identifies the node and the number of fully connected subnets that remain when that node fails. If the network has no SPF nodes, simply output the text “No SPF nodes” instead of a list of SPF nodes.
Sample Input
1 2
5 4
3 1
3 2
3 4
3 5
0

1 2
2 3
3 4
4 5
5 1
0

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

0
Sample Output
Network #1
SPF node 3 leaves 2 subnets

Network #2
No SPF nodes

Network #3
SPF node 2 leaves 2 subnets
SPF node 3 leaves 2 subnets

题意: 求删除割点后剩下的连通分量数。

思路: tarjan算法的核心在于记录搜索遍历的时间顺序,加上一个追溯值(所谓low[u])后,使得从点u出发能够互相到达的部分追溯值与u都相同(也就是强连通啦(#^. ^#))。本题中求的是割点,判断方法是dfn[u] ≤ low[v],也就是说,从v的子节点出发,不经过u,不管经过哪个节点,都不能到达u或比u更早的点。 而算连通分量数的话,每遇到一次上述情况cut[u]++。结果就是cut[u]+1;

注意每次搜索时特判一下根节点,根节点答案就是cut[u],而且根节点只有搜索了至少2个儿子的时候才能作为割点。

#include 
#include 
#include 
#include 
using namespace std;

const int maxn = 1e3 + 7;
vector<int>G[maxn];
vector<int>ans;
int low[maxn],dfn[maxn],cut[maxn],f[maxn],dfs_clock;

void init()
{
    dfs_clock = 0;
    for(int i = 0;i <= 1000;i++)
        G[i].clear();
    memset(low,0,sizeof(low));
    memset(dfn,0,sizeof(dfn));
    memset(cut,0,sizeof(cut));
    memset(f,0,sizeof(f));
    ans.clear();
}

void add(int u,int v)
{
    G[u].push_back(v);
    G[v].push_back(u);
}

void tarjan(int u,int fa)
{
    low[u] = dfn[u] = ++dfs_clock;
    int son = 0;
    for(int i = 0;i < G[u].size();i++)
    {
        int v = G[u][i];
        if(!dfn[v])
        {
            son++;
            tarjan(v,u);
            low[u] = min(low[u],low[v]);
            if(low[v] >= dfn[u])
                cut[u]++;
        }
        else if(dfn[v] < dfn[u] && v != fa)
            low[u] = min(low[u],dfn[v]);
    }
    if(fa < 0)//根
    {
        if(son >= 2)
            ans.push_back(u);
    }
    else if(cut[u] >= 1)
    {
        ans.push_back(u);cut[u]++;
    }
}

int main()
{
    int u,v;
    int kase = 0,mx = 0;
    while(~scanf("%d",&u) && u)
    {
        init();
        scanf("%d",&v);add(u,v);
        mx = max(mx,u);
        mx = max(mx,v);
        while(scanf("%d",&u) && u)
        {
            scanf("%d",&v);add(u,v);
            mx = max(mx,u);
            mx = max(mx,v);
        }
        for(int i = 1;i <= mx;i++)
        {
            if(!dfn[i])
                tarjan(i,-1);
        }
        printf("Network #%d\n",++kase);
        sort(ans.begin(),ans.end());
        if(ans.size() > 0)
        {
            for(int i = 0;i < ans.size();i++)
            {
                printf("  SPF node %d leaves %d subnets\n",ans[i],cut[ans[i]]);
            }
        }
        else
        {
            printf("  No SPF nodes\n");
        }
        puts("");
    }
    return 0;
}

你可能感兴趣的:(#,tarjan)