Tarjan无向图求割点割桥模版, O(n+m), 无重边/重边情况均可处理

来源:互联网 发布:试客联盟软件 编辑:程序博客网 时间:2024/06/13 20:56
/*  Function:Tarjan无向图求割点割桥, O(n+m), 无重边/重边情况均可处理 1. 求出所有的桥,再将 */#include<bits/stdc++.h>#define rep(i,a,b) for(int i=a; i<=b; ++i)#define repp(i,a,b) for(int i=b; i>=a; --i)#define fi first#define se second#define mp make_pair#define pb push_back#define ms(a, b) memset(a, b, sizeof(a))using namespace std;typedef long long ll;typedef pair<int, int> pii;typedef vector<int>vi;const int maxn = 1e5+7;// 建边 struct edge{    int to, next;}e[maxn << 1]; //两倍空间 int fi[maxn], id=0;void adde(int u, int v){    e[id].to = v;    e[id].next = fi[u];    fi[u] = id++;    return ;}int dfn[maxn], low[maxn], sig;  bool cut[maxn]; //是否为割点typedef pair<int, int> pii; vector<pii>cutbg; //保存割桥void init(){    ms(fi, -1), ms(dfn, 0), ms(low, 0), ms(cut, false);    sig = id = 0;    cutbg.clear();    return ;} void tarjan(int u,int eid) // eid指父亲边   {      low[u] = dfn[u] = ++sig;      int i, son = 0; // 记录子树     for(i = fi[u]; ~i; i = e[i].next){          int to = e[i].to;          if( i == (eid^1) ) continue;  //重边         if( !dfn[to] ){              son++;            tarjan( to, i );              low[u]=min(low[u],low[to]);              if(low[to] > dfn[u]){ // 判断割桥                 cutbg.push_back(make_pair(u, e[i].to));             }            if(low[to] >= dfn[u]){ // 判断割点                 cut[u] = true;            }        }          else low[u]=min(low[u],dfn[to]);      }      if(eid == -1 && son <= 1) cut[u] = 0; // 当u为根节点,且u只有一个子树或没有子树的时候 , u一定不是割点 }  int main(){    //freopen("in.txt", "r", stdin);    int n, m;    while(scanf("%d%d",&n,&m)==2&&n)      {          init();        int u, v;        rep(i, 1, m){              scanf("%d%d",&u,&v);              adde(u,v);            adde(v, u);         }          tarjan(1,-1); // 若确定为联通图        /*            若不确定是否是联通图            rep(i, 1, n){                if(!dfn[i]){                    tarjan(i,-1);                }            }        */         cout <<"割点 : "  ;        rep(i, 1, n){            if(cut[i]){                cout << i<<" ";            }        }        cout << endl;        cout << "割桥 :\n";        int len = cutbg.size();        rep(i, 0, len-1){            printf("(%d,%d)\n", cutbg[i].fi, cutbg[i].se);        }     }      return 0;}
阅读全文
0 0
原创粉丝点击