图论---求割点,求桥(tarjan) (模板)

来源:互联网 发布:wampserver mac 编辑:程序博客网 时间:2024/05/29 00:31

无向图求桥和求割点用的是同一个做法。
具体的原理可以看大白书和 @泳裤王子,无向连通图的割点、桥

下面是代码:
//现在发现这么写不能排除重边,需要特判一下!桥如果有重边就不是桥了

#include <iostream>  #include <cstdio>  #include <cstdlib>  #include <cstring>  #include <cmath>  #include <stack>  #include <bitset>  #include <queue>  #include <set>  #include <map>  #include <string>  #include <algorithm>  using namespace std;#define clr(a,b) memset(a,b,sizeof(a))#define pb(a) push_back(a)#define fir first#define se second#define LL long longtypedef pair<int,int> pii;typedef pair<LL,int> pli;typedef pair<LL,LL> pll;const int maxn = 1e6+5;const LL inf = 0x3f3f3f3f3f3f3f3f;LL mod = 1e9+7;double eps = 0.00000001;double PI = acos(-1);vector<int> g[1005];int n,low[1005],dfn[1005],dfs_clock,iscut[1005];vector<pii> ans;//dfn[i]为点i在dfs遍历中的次序//low[i]为点i能通过非树边回到的遍历序号最小的点//dfs_clock用来计数,iscut用来表示是否是割点。//ans用pair来存桥void init() {  //初始化    for(int i = 0;i <= n;i++) g[i].clear();    ans.clear();    dfs_clock = 0;    clr(dfn,0);    clr(iscut,0);    clr(low,0);}int dfs(int u,int fa) {  //dfs求每个点的dfn和low    low[u] = dfn[u] = ++dfs_clock;    int child = 0;    for(int i = 0;i < g[u].size();i++) {        int v = g[u][i];        if(!dfn[v]) {            child++;            low[v] = dfs(v,u);            low[u] = min(low[u],low[v]);            if(low[v] >= dfn[u]) {   //判断割点                iscut[u] = true;            }            if(low[v] > dfn[u]) {  //判断桥                int a = u,b = v;                if(a > b) swap(a,b);                ans.pb(make_pair(a,b));            }        }        else if(dfn[v] < dfn[u] && v != fa) {            low[u] = min(low[u],dfn[v]);        }    }    if(fa < 0 && child == 1) iscut[u] = false;  //特判树根是不是割点    return low[u];}void input() {  //输入    int u,v;    for(int i = 1;i <= n;i++) {        char str[50];        scanf("%d%s",&u,str);        int x = 0;        for(int j = 0;str[j];j++) {            if(str[j] >= '0' && str[j] <= '9') x = x*10+(str[j]-'0');        }        for(int i = 1;i <= x;i++) {            scanf("%d",&v);            g[u].pb(v);            g[v].pb(u);        }    }}int main() {    while(scanf("%d",&n) != EOF) {        int u,v;        init();        input();        for(int i = 1;i <= n;i++)            if(!dfn[i]) dfs(i,-1);        /*for(int i = 1;i <= n;i++) {            for(int e : g[i]) printf("%d ",e);            cout<<endl;        }*/        /*int ans = 0;        for(int i = 1;i <= n;i++)    //输出割点            if(iscut[i]) ans++;        cout<<ans<<endl;*/        printf("%d critical links\n",ans.size());  //输出桥        sort(ans.begin(),ans.end());        for(auto it : ans) cout<<it.fir<<" - "<<it.se<<endl;        cout<<endl;    }}/*80 1 11 3 2 0 32 2 1 33 3 1 2 44 1 37 1 66 1 75 0*/
原创粉丝点击