无向图的割点与桥 求解模板

 

不懂的可以先看这:1          2         3

 

求桥

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 10;
const int maxm = 4e5 + 10;
struct egde{ int v, nxt; }Edge[maxm];
int Head[maxn], cnt;
int LOW[maxn], DFN[maxn], Fa[maxn], INDEX;
int N, M;
struct no
{
    int u,v;
}BG[maxm];
bool cmp(no a , no b)
{
    if(a.u!=b.u)
    return a.u<b.u;
    return a.v<b.v;
}
 void init()
{
    for(int i=0; i<=N; i++)
        Head[i] = LOW[i] = DFN[i] = -1, Fa[i] = 0;
    cnt = INDEX = 0;
}

inline void AddEdge(int from, int to)
{
    Edge[cnt].v = to;
    Edge[cnt].nxt = Head[from];
    Head[from] = cnt++;
}

void Tarjan(int v, int Father)
{
    Fa[v] = Father;
    DFN[v] = LOW[v] = INDEX++;
    for(int i=Head[v]; i!=-1; i=Edge[i].nxt){
        int Eiv = Edge[i].v;
        if(DFN[Eiv] == -1){
            Tarjan(Eiv, v);
            LOW[v] = min(LOW[v], LOW[Eiv]);
        }
        else if(Father != Eiv)
            LOW[v] = min(LOW[v], DFN[Eiv]);
    }
}

void solve()
{
    int ans = 0;
    Tarjan(0, -1);

    for(int i=0; i<N; i++){
        int v = Fa[i];
        if(v >= 0 && LOW[i] > DFN[v]){//满足是桥的条件
            // v->i is bridge
            BG[ans].u=min(v,i);//贮存
            BG[ans++].v = max(v,i);
        }
    }
    sort(BG, BG+ans,cmp);
    printf("%d\n", ans);
    if(ans > 0){
        for(int i=0; i<ans; i++)
            printf("%d %d\n", BG[i].u, BG[i].v);
    }puts("");
}

int main(void)
{
    while(~scanf("%d %d", &N, &M)){
        init();
        int from, to;
        while(M--){
            scanf("%d %d", &from, &to);
            AddEdge(from, to);
            AddEdge(to, from);
        }
       solve();
    }
    return 0;
}
View Code

求割点

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 10;
const int maxm = 4e5 + 10;
struct no{ int v, nxt; }Edge[maxm];
int head[maxn], cnt;
int low[maxn], DFN[maxn], Fa[maxn], INDEX;
int is_cut[maxn];
int N, M;

inline void init()
{
    for(int i=0; i<=N; i++)
        head[i] = low[i] = DFN[i] = Fa[i] = -1,
        is_cut[i] = false;
    cnt = INDEX = 0;
}

 inline void AddEdge(int from, int to)
{
    Edge[cnt].v = to;
    Edge[cnt].nxt = head[from];
    head[from] = cnt++;
}

void Tarjan(int v, int Father)
{
    Fa[v] = Father;
    DFN[v] = low[v] = INDEX++;
    for(int i=head[v]; i!=-1; i=Edge[i].nxt){
        int Eiv = Edge[i].v;
        if(DFN[Eiv] == -1){
            Tarjan(Eiv, v);
            low[v] = min(low[v], low[Eiv]);
        }
        else if(Father != Eiv)
            low[v] = min(low[v], low[Eiv]);
    }
}

void solve()
{
    int Cut_Num = 0;
    int Root_Child  = 0;
    Tarjan(0, -1);
    for(int i=1; i<N; i++){
        int v = Fa[i];
        if(v == 0) Root_Child++;
        else if(low[i] >= DFN[v] && !is_cut[v]) is_cut[v] = true, Cut_Num++;
    }
    if(Root_Child > 1) is_cut[0] = true, Cut_Num++;
//求桥
//    for(int i=0; i<n; i++){
//        int v = Fa[i];
//        if(v >= 0 && low[i] > DFN[v])
//            // v->i is bridge
//    }

///-----------------求割点
    printf("%d\n", Cut_Num);
    if(Cut_Num != 0){
        for(int i=0; i<N; i++)
            if(is_cut[i])
                printf("%d ", i);
        puts("");
    }puts("");
///-----------------
}

int main(void)
{
    while(~scanf("%d %d", &N, &M)){
        init();
        int from, to;
        while(M--){
            scanf("%d %d", &from, &to);
            AddEdge(from, to);
            AddEdge(to, from);
        }
        solve();
    }
    return 0;
}
View Code

 

posted @ 2018-09-19 14:03  shuai_hui  阅读(163)  评论(0编辑  收藏  举报