用dfs求无向图的割点割边

图的割点简单问题代码模版:

输入n,m代表顶点个数和边数,下面m行是m条无向边

输出各个割点:

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m,index,root;
int v[100],u[100];
int first[15],next[100];
int time[15],low[15];
bool vis[15];
void dfs(int cur)
{
    int child=0;
    time[cur]=++index; //时间戳 
    low[cur]=index;   //可追溯到先前时间戳 
    for(int t=first[cur];t!=-1;t=next[t])
    {
        if(!time[v[t]]){
            child++;
            dfs(v[t]);
            low[cur]=min(low[cur],low[v[t]] );
            if(cur!=root&&low[v[t] ]>=time[cur]){
                vis[cur]=1;
            }
            if(cur==root&&child>1) vis[cur]=1; //当判断根是不是割点的时候要单独拿出来判断,当从根dfs有1个以上儿子的时候即使割点 
        }
        else {
            low[cur]=min(low[cur],time[v[t] ]);
        }
    }

}
int main()
{
    memset(first,-1,sizeof(first));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&u[i],&v[i]);
        next[i]=first[u[i] ];
        first[u[i]] = i;
        u[i+m]=v[i],v[i+m]=u[i];
        next[i+m]=first[u[i+m] ];
        first[u[i+m] ]=i+m;
    }
    root=1;
    dfs(root);
    for(int i=1;i<=n;i++)
        if(vis[i]) printf("%d ",i);
    puts("");
  //  for(int i=1;i<=n;i++) printf("time[%d]=%d ",i,time[i]);
  //  puts("");
  //  for(int i=1;i<=n;i++) printf("low[%d]=%d ",i,low[i]);
  //  puts("");
    return 0;
}

图的割边简单问题代码模版

输入n,m代表顶点个数和边数,下面m行是m条无向边

输出各条割边:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m,root,index;
int first[15],next[100];
int time[15],low[15];
int v[100],u[100];
void dfs(int fa,int cur) //这时必须有fa(父亲)这个参数,和图的割点不样了
{
    time[cur]=++index; //时间戳 
    low[cur]=index; //可追溯到的时间戳 
    for(int t=first[cur];t!=-1;t=next[t]){
        if(!time[v[t] ]){
            dfs(cur,v[t]);
            low[cur]=min(low[cur],low[v[t]]);
            if(low[v[t]]>time[cur]) printf("%d--%d\n",cur,v[t]);  //这也是和图的割点的区别之一。不要对cur==root的时候进行特判了。
        }
        else if(v[t]!=fa){
            low[cur]=min(low[cur],time[v[t] ]);
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    memset(first,-1,sizeof(first));
    for(int i=1;i<=m;i++){
        scanf("%d%d",&u[i],&v[i]);
        next[i]=first[u[i] ];
        first[u[i] ]= i;
        u[i+m]=v[i];
        v[i+m]=u[i];
        next[i+m]=first[u[i+m] ];
        first[u[i+m] ]=i+m;
    }
    root=1;
    dfs(root,root);
  //  for(int i=1;i<=n;i++) printf("time[%d]=%d ",i,time[i]);
  //  puts("");
  //  for(int i=1;i<=n;i++) printf("low [%d]=%d ",i,low[i]);
  //  puts("");
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用Python实现无向图的最小点集的示例代码: ``` from collections import defaultdict def min_cut_points(graph): n = len(graph) low = [0] * n dfn = [0] * n cut_points = set() def dfs(u, parent, time): children = 0 low[u] = dfn[u] = time for v in graph[u]: if not dfn[v]: children += 1 dfs(v, u, time + 1) low[u] = min(low[u], low[v]) if parent == -1 and children > 1: cut_points.add(u) elif parent != -1 and low[v] >= dfn[u]: cut_points.add(u) elif v != parent: low[u] = min(low[u], dfn[v]) for i in range(n): if not dfn[i]: dfs(i, -1, 1) return cut_points ``` 该函数接受一个字典,表示无向图的邻接表。它返回一个集合,其中包含无向图的最小点集。 该算法使用了深度优先搜索来查找点。对于每个节点,它维护了两个数组:dfn和low。dfn表示节点被发现的时间,low表示节点和它可达的节点之间的最小dfn值。 在搜索过程中,如果一个节点v未被发现,则将它标记为已发现,并为它更新dfn和low值。对于每个邻居节点v,如果v是u的父节点,则children计数器加1。如果v不是u的父节点,并且low[v] >= dfn[u],则u是一个点。如果u是根节点并且children大于1,则u也是一个点。 最终,返回所有点的集合。 下面是一个使用示例: ``` graph = defaultdict(list) graph[0] = [1, 2] graph[1] = [0, 2] graph[2] = [0, 1, 3] graph[3] = [2, 4, 5] graph[4] = [3] graph[5] = [3] cut_points = min_cut_points(graph) print(cut_points) # 输出 {2, 3} ``` 这个例子中,图包含6个节点和7条边。最小点集包括节点2和节点3。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值