poj1144 Network【tarjan求割点】

转载请注明出处,谢谢:http://www.cnblogs.com/KirisameMarisa/p/4319585.html   ---by 墨染之樱花

【题目链接】http://poj.org/problem?id=1144

【题目描述】(半天才看明白。。。)给图求割点个数

【思路】直接套求割点的模板即可,就是要注意输入比较坑。代码见下,附注释

#include <iostream>
#include <ios>
#include <iomanip>
#include <functional>
#include <algorithm>
#include <vector>
#include <sstream>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <cstring>
#include <climits>
using namespace std;
#define XINF INT_MAX
#define INF 1<<30
#define MAXN 110
#define eps 1e-10
#define zero(a) fabs(a)<eps
#define sqr(a) ((a)*(a))
#define MP(X,Y) make_pair(X,Y)
#define PB(X) push_back(X)
#define PF(X) push_front(X)
#define REP(X,N) for(int X=0;X<N;X++)
#define REP2(X,L,R) for(int X=L;X<=R;X++)
#define DEP(X,R,L) for(int X=R;X>=L;X--)
#define CLR(A,X) memset(A,X,sizeof(A))
#define IT iterator
#define PI  acos(-1.0)
#define test puts("OK");
#define _ ios_base::sync_with_stdio(0);cin.tie(0);
typedef long long ll;
typedef pair<int,int> PII;
typedef priority_queue<int,vector<int>,greater<int> > PQI;
typedef vector<PII> VII;
typedef vector<int> VI;
#define X first
#define Y second

struct edge
{
    int to,next;
    edge(int _to=0,int _next=0){to=_to;next=_next;}
} edges[MAXN*MAXN];

int head[MAXN];
int low[MAXN];   //非父边指向的最早访问的祖先
int dfn[MAXN];   //时间戳
int cnt;     //记录时间
bool inst[MAXN];
bool cut[MAXN];   //判断是否是割点 

inline void addedge(int x,int y,int &eCnt)
{
    edge e(y,0);
    edges[eCnt]=e;
    edges[eCnt].next=head[x];
    head[x]=eCnt;
    eCnt++;
}

void tarjan(int u,int fa)
{
    low[u]=dfn[u]=++cnt;
    inst[u]=1;
    int tot=0;
    for(int i=head[u];i;i=edges[i].next)
    {
        int v=edges[i].to;
        if(v==fa)
            continue;
        if(!dfn[v])
        {
            tarjan(v,u);
            tot++;
            if(low[v]<low[u])
                low[u]=low[v];
            if(u==0 && tot>1)   //根结点有两个或两个以上子节点时才是割点
                cut[u]=1;
            else if(u!=0 && low[v]>=dfn[u])   //非根结点为割点当且仅当存在一个子节点v,使v以及v的后代都没有返回u的祖先的反向边
                cut[u]=1;
        }
        else if(inst[v] && dfn[v]<low[u])
            low[u]=dfn[v];
    }
}

int main()
{_
    int n;
    while(~scanf("%d",&n) && n)
    {
        CLR(head,0);CLR(dfn,0);
        CLR(inst,0);CLR(cut,0);
        cnt=0;
        int u;
        int ec=1;
        while(scanf("%d",&u) && u)
        {
            u--;
            char c;
            int v;
            while(scanf("%c",&c) && c!=‘\n‘)
            {
                scanf("%d",&v);
                v--;
                addedge(u,v,ec);
                addedge(v,u,ec);
            }
        }
        tarjan(0,-1);
        int ans=0;
        REP(i,n)
            if(cut[i])
                ans++;
        printf("%d\n",ans);
    }
    return 0;
}

时间: 2024-10-16 13:29:18

poj1144 Network【tarjan求割点】的相关文章

[POJ1144][BZOJ2730]tarjan求割点

求割点 一种显然的n^2做法: 枚举每个点,去掉该点连出的边,然后判断整个图是否联通 用tarjan求割点: 分情况讨论 如果是root的话,其为割点当且仅当下方有两棵及以上的子树 其他情况 设当前节点为u,一个儿子节点为v 存在low[v]>=dfn[u],也就是说其儿子节点v能连到的最前面的点都在u的下面 也就是当u断开的时候,u之前的点与以v为根的子树必然分成两个独立的块 那么这个时候u就是割点 Network A Telephone Line Company (TLC) is estab

poj1144 tarjan求割点

poj1144 tarjan求割点 额,算法没什么好说的,只是这道题的读入非常恶心. 还有,理解tarjan一定要用递归树,配合横边回边前边树边等来想.. #include <cctype> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn=100, maxm=5000; struct Graph{ struct Edge

POJ 1144 &amp; Uva 315 Network 【求割点数目】

Network Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 10855   Accepted: 5020 链接:http://poj.org/problem?id=1144 Description A Telephone Line Company (TLC) is establishing a new telephone cable network. They are connecting several places

UESTC 900 方老师炸弹 --Tarjan求割点及删点后连通分量数

Tarjan算法. 1.若u为根,且度大于1,则为割点 2.若u不为根,如果low[v]>=dfn[u],则u为割点(出现重边时可能导致等号,要判重边) 3.若low[v]>dfn[u],则边(u,v)为桥(封死在子树内),不操作. 求割点时,枚举所有与当前点u相连的点v: 1.是重边: 忽略 2.是树边: Tarjan(v),更新low[u]=min(low[u],low[v]); 子树个数cnt+1.如果low[v] >= dfn[u],说明是割点,割点数+1 3.是回边: 更新lo

tarjan求割点割边的思考

这个文章的思路是按照这里来的. 首先来看求割点.割点必须满足去掉其以后,图被分割.tarjan算法考虑了两个: 一,根节点如果有两颗及以上子树,它就是割点.这个应该说是显然的. 二,对于普通的结点a,如果它递归树的子树中,有任意节点b的low[b]<dfn[a],那么它就不是割点,反之则是割点. 我们先来证明如果low[b]<dfn[a],a一定不是割点.low[b]<dfn[a]说明有一个结点,通过非树枝边可以访问到a以前的结点,那么显然去掉a以后,b依然与a以上的递归树联通,a不是割

poj1144 tarjan求割点 裸题

Network Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 11684   Accepted: 5422 Description A Telephone Line Company (TLC) is establishing a new telephone cable network. They are connecting several places numbered by integers from 1 to N

UVA - 315 Network(tarjan求割点的个数)

题目链接:https://vjudge.net/contest/67418#problem/B 题意:给一个无向连通图,求出割点的数量.首先输入一个N(多实例,0结束),下面有不超过N行的数,每行的第一个数字代表后面的都和它存在边,0表示行输入的结束. 题解:简单的求割点模版,所谓割点就是去掉这一个点还有于这个点链接的边之后使得原来的图连通块增加. 由于这是模版题代码会加上注释. #include <iostream> #include <cstring> using namesp

[UVA315]Network(tarjan, 求割点)

题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=251 求割点,除了输入用strtok和sscanf处理输入以外,对于求割点的tarjan算法有了进一步理解. 特别注意88行,如果u是根并且至少两个儿子,那它一定是割点无误,还有第二个情况用如图代表: 这个例子里显然:low[4]=2,dfn[4]=4,dfn[3]=3.现dfs到

连通分量模板:tarjan: 求割点 &amp;&amp; 桥 &amp;&amp; 缩点 &amp;&amp; 强连通分量 &amp;&amp; 双连通分量 &amp;&amp; LCA(最近公共祖先)

PS:摘自一不知名的来自大神. 1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点. 2.割点集合:在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个连通块,就称这个点集为割点集合. 3.点连通度:最小割点集合中的顶点数. 4.割边(桥):删掉它之后,图必然会分裂为两个或两个以上的子图. 5.割边集合:如果有一个边集合,删除这个边集合以后,原图变成多个连通块,就称这个点集为割边集合. 6.边连通度:一个图的边连通度的定义为,最