图基础模板

来源:互联网 发布:淘宝造物节h5 源码 编辑:程序博客网 时间:2024/06/05 20:11

1、判断割顶:

对于根节点当然简单,当且仅当它有两个或者是更多的子节点时,他才是割顶。

对于其他节点,

定理:在无向图连通图G的DFS树中,非根节点u是G的割顶当且仅当u存在一个子节点v,使得v及其所有后代都没有反向边连回u的祖先

#include <iostream>#include <cstdlib>#include <cstdio>#include <algorithm>#include <cstring>#include <stack>#include <vector>#include <queue>#include <map>using namespace std;const int maxn = 1000;vector<int> G[maxn];int pre[maxn], dfs_clock, low[maxn], n; ///访问当前点的顺序标志,dfs_clock表示时间戳,low[v]为v及其后代所能练会的最早的祖先的pre值bool iscut[maxn];  ///是否为割顶void init(){    for(int i=0; i<n; i++)        G[i].clear();    memset(iscut, false, sizeof(iscut));    memset(pre, 0, sizeof(pre));    dfs_clock = 0;}int dfs(int u, int fa)  //u在DFS树中的父结点是fa   返回u的最小low{    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])     //没有访问过v, 没有必要用vis标记了        {            child++;            int lowv = dfs(v, u);  ///获得子节点最小low            if(lowv >= pre[u])   iscut[u] = true;            lowu = min(lowu, lowv); //用后代的 low 函数更新 u 的 low 函数        }        else if(pre[v] < pre[u] && v != fa)  //(u,v)为反向边              lowu = min( lowu, pre[v] );   //用反向边更新 u 的 low 函数    }     if( fa < 0 && child < 2 )  //根节点当且仅当它有两个或者更多的子节点时才是割顶        iscut[u] = false;    low[u] = lowu;    return lowu;}int main(){    int m, u, v;    scanf("%d%d", &n, &m);    init();    for(int i=0; i<m; i++)    {        cin>>u>>v;        G[u].push_back(v);        G[v].push_back(u);    }    for(int i=0; i<n; i++)        if(!pre[i])          dfs(i, -1);    for(int i=0; i<n; i++)  //将割点输出        if(iscut[i])             printf("%d ", i);            putchar('\n');        return 0;}

其他重点图基础见:链接




0 0
原创粉丝点击