【算法练习】 HihoCoder 1190 连通性·四(点双连通分量)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/pengwill97/article/details/81951677

题意

对于每个点双连通分量,输出其中的边编号最小的值。

题解

tarjan算法。
本质还是求割顶,然后边tarjan边计算。
注意因为根节点不一定是割顶。为了达到题目的输出要求,不用判断根节点是不是割顶了。这样的话,可以直接可以把1所在的组全部赋值上。

代码

#include<bits/stdc++.h>
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
const int nmax = 1e6+7;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const ull p = 67;
const ull MOD = 1610612741;
int head[nmax], tot, dfs_clock, cut_cnt, n, m;
int dfn[nmax], low[nmax], mini[nmax], bccid[nmax];
bool iscut[nmax];
struct edge{
    int to, nxt, id, ans;
}e[nmax<<1];
void add_edge(int u, int v, int id) {
    e[tot].to = v;
    e[tot].nxt = head[u];
    e[tot].id = id;
    head[u] = tot ++;
}
stack<int> S;
void tarjan(int u , int fa) {
    dfn[u] = low[u] = ++dfs_clock;
    for(int i = head[u]; i != -1; i = e[i].nxt) {
        int v = e[i].to;
        if(fa == v)
            continue;
        if(!dfn[v]) {
            S.push(e[i].id);
            tarjan(v, u);
            low[u] = min(low[u], low[v]);
            if(low[v] >= dfn[u]) {
                cut_cnt ++;
                mini[cut_cnt] = INF;
                for(;;) {
                    int now = S.top();
                    S.pop();
                    bccid[now] = cut_cnt;
                    mini[cut_cnt] = min(mini[cut_cnt], now);
                    if(now == e[i].id)
                        break;
                }

            }
        } else if(v != fa && dfn[v] < dfn[u]) {
            S.push(e[i].id);
            low[u] = min(low[u], dfn[v]);

        }
    }
}

int main(){
    memset(head, -1, sizeof head);
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= m; ++i) {
        int u, v;
        scanf("%d %d", &u, &v);
        add_edge(u, v, i);
        add_edge(v, u, i);
    }
    for(int i = 1; i <= n; ++i) {
        if(!dfn[i])
            tarjan(i, -1);
    }
    printf("%d\n",cut_cnt);
    for(int i = 1; i <= m; ++i) {
        printf("%d ", mini[bccid[i]]);
    }
    printf("\n");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/pengwill97/article/details/81951677