用Tarjan算法求无向连通图割点&&割边

来源:互联网 发布:广州软件开发培训班 编辑:程序博客网 时间:2024/05/14 02:37
/**    割点割边挺好理解的,割点就是一个无向连通图,把其中一个点    挖掉剩下的图不连通,割边就是把一条边砍掉不连通    比如:有一个通信网络,要求一颗炸弹,把这个通信网络搞得不连通,问    炸哪个点或哪条边。    Tarjan 算法实现求割边和割点很类似,不过还是有点不同,复杂度为O(N+M)    下面用 <vector> 存边写下*///求割点#include <vector>bool cut[nMax];   //cut[x] = ture 代表x 为割点int dfn[nMax], low[nMax];  //dfn[x] x是当前层次,low[x] x是能到得的最低层次//这两个或许有点摸不着头脑,不过没关系,//查下tarjan 自己画画差不多就能理解,tarjan只是个帅哥名字,没那么可怕vector<int> adj[nMax];int rt, rt_num; //起始节点和访问此结点的次数,如果大于一则rt也为割点//用于判断起始结点是否也是割点/**    nMax为点的个数;    rt选任意一点;    rt_num = 0;*/void addEdge(int u, int v) {    adj[u].push_back(v);    adj[v].push_back(u);}void findcut(int dep, int u) {    dfn[u] = low[u] = dep;    for (int i=0; i<adj[u].size(); i++) {        int v = adj[u][i];        if (!dfn[v]) {            findcut(dep+1, v);            if (u == rt)                rt_num++;            else {                low[u] = min(low[u], low[v]);                if (low[v] >= dfn[u])                    cut[u] = true;  //如果满足这个条件则u 为割点            }        }        else            low[u] = min(low[u], dfn[v]);    }}int main() {    //初始化    /**        dfn = 0, cut = 0, rt_num = 0;        adj[i].clear(); //对边集进行清空    */    //建好图后调用    findcut(1, rt); //rt 任选 1 - n    if (rt_num > 1)        cut[rt] = true;    //则cut 中为 true 的即为割点    return 0;}//求割边void findcut(int dep, int u, int f) {    dfn[u] = low[u] = dep;    for (int i=0; i<adj[u].size(); i++) {        int v = adj[u][i];        if (!dfn[v]) {            findcut(dep+1, v, u);            low[u] = min(low[u], low[v]);            if (low[v] > dfn[u])                cut[u][v] = true;  //如果满足这个条件则adj(u, v)为割边        }        else if (f != v)            low[u] = min(low[u], dfn[v]);    }}//调用即可    findcut(1, 1, 0);/**    还是那句话,模板都会用,关键在转换*/ 收藏于 2012-01-09来自于百度空间

0 0
原创粉丝点击