ZOJ - 1119 SPF

来源:互联网 发布:微单 人像 知乎 编辑:程序博客网 时间:2024/06/05 14:46

题目: SPF


题意:给一个网络(实质是一副无向图),每一个节点为一台计算机,输出:哪一台计算机是割点 , 移去它之后网络被分成了几块


思路:无向图求割点套模板,所谓割点(参考):

1.如果点v是DFS序列的根节点,则如果v有一个以上的孩子,则v是一个割点。

2.如果v不是DFS序列根节点,并且点v的任意后继u能追溯到最早的祖先节点low[u]>=dfn[v],则v是一个割点。

用当前子节点计数器count统计去掉割点后的连通分支,如果是dfs根节点则为count,否则为count+1

代码:

#pragma comment(linker, "/STACK:102400000,102400000")#include "iostream"#include "cstring"#include "algorithm"#include "cmath"#include "cstdio"#include "sstream"#include "queue"#include "vector"#include "string"#include "stack"#include "cstdlib"#include "deque"#include "fstream"#include "map"using namespace std;typedef long long LL;const int INF = 0x1fffffff;const int MAXN = 1000000+100;#define eps 1e-14struct node{    int now;    int next;}e[1010];int head[1010] , vis[1010] , low[1010] , dfn[1010], cnt , clo , set[1010];void add(int x , int y){    e[cnt].now = y;    e[cnt].next = head[x];    head[x] = cnt++;}void init(){    memset(head,-1,sizeof(head));    memset(set,0,sizeof(set));    memset(dfn,0,sizeof(dfn));    memset(low,0,sizeof(low));    memset(vis,0,sizeof(vis));    clo=0;    cnt=0;}void gedian(int fa , int cur){    int count=0;                        //当前点的孩子数    dfn[cur] = low[cur] = ++clo;    vis[cur] = 1;    for(int i = head[cur] ; i!=-1 ; i = e[i].next)    {        int now = e[i].now;        if(!vis[now])        {            gedian(cur,now);            count++;            if(low[now] < low[cur])             //更新cur的祖先:若cur的子节点能追溯到更早的祖先,则cur也能追溯到                low[cur] = low[now];            if(!fa && count>1)                  //判断条件1                set[cur] = count;            else if(fa && dfn[cur] <= low[now]) //判断条件2                set[cur] = count+1;        }        else if(now != fa && low[cur] > low[now])//若已被访问,更新更早祖先            low[cur] = low[now];    }}int main(){    int a,b;    int kase=1;    while(~scanf("%d",&a) && a)    {        init();        do        {            scanf("%d",&b);            add(a,b);            add(b,a);            scanf("%d",&a);        }while(a);        if(kase!=1)            puts("");        gedian(0,1);        printf("Network #%d\n",kase++);        bool ok = false;        for(int i = 0 ; i < 1010 ; i++)            if(set[i])            {                ok = true;                printf("  SPF node %d leaves %d subnets\n" , i , set[i]);            }        if(!ok)            printf("  No SPF nodes\n");    }    return 0;}