hihor学习日记:hiho一下 第五十五周 (点的双连通分量)

http://hihocoder.com/contest/hiho55/problem/1

与边的双联通分量类似,这个是求的割点
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

伪代码:

void dfs(int u) {
	//记录dfs遍历次序
	static int counter = 0;	
	
	//记录节点u的子树数
	int children = 0;
	
	ArcNode *p = graph[u].firstArc;
	visit[u] = 1;

	//初始化dfn与low
	dfn[u] = low[u] = ++counter;

	for(; p != NULL; p = p->next) {
		int v = p->adjvex;
		if(edge(u,v)已经被标记) continue; 

		//节点v未被访问,则(u,v)为树边
		if(!visit[v]) {
			children++;
			parent[v] = u;
			edgeStack[top++] = edge(u,v); // 将边入栈
			dfs(v);
			
			low[u] = min(low[u], low[v]);

			//case (1)
			if(parent[u] == NIL && children > 1) {
				printf("articulation point: %d\n", u);
				// mark edge
				// 将边出栈,直到当前边出栈为止,这些边标记为同一个组
				do {
					nowEdge = edgeStack[top];
					top--;
					// 标记nowEdge
				}	while (nowEdge != edge(u,v))
			}

			//case (2)
			if(parent[u] != NIL && low[v] >= dfn[u]) {
				printf("articulation point: %d\n", u);
				// mark edge
				// 将边出栈,直到当前边出栈为止,这些边标记为同一个组
				do {
					nowEdge = edgeStack[top];
					top--;
					// 标记nowEdge
				}	while (nowEdge != edge(u,v))
			}
			
		}

		//节点v已访问,则(u,v)为回边
		else if(v != parent[u]) {
			edgeStack[top++] = edge(u,v);
			low[u] = min(low[u], dfn[v]);
		}
	}
}

AC代码:

#include <bits/stdc++.h>

using namespace std;
#define LL long long
const int Mod = 1e9 + 7;
const int maxn = 2e5 + 5;
const double eps = 0.00000001;
const int INF = 0x3f3f3f3f;

struct Edge{
    int u, v, nxt, id;
}edge[maxn << 1];

int tot, top, head[maxn];
int dfn[maxn], low[maxn], belong[maxn], par[maxn], Stack[maxn], Min[maxn];
int n, m, cnt;

void init() {
    cnt = top = tot = 0;
    memset(head, -1, sizeof(head));
    memset(belong, -1, sizeof(belong));
    memset(par, -1, sizeof(par));
    memset(Min, INF, sizeof(Min));
    memset(dfn, 0, sizeof(dfn));

}

void addEdge(int u, int v, int id) {
    edge[tot].u = u;
    edge[tot].v = v;
    edge[tot].nxt = head[u];
    edge[tot].id = id;
    head[u] = tot ++;

    edge[tot].u = v;
    edge[tot].v = u;
    edge[tot].nxt = head[v];
    edge[tot].id = id;
    head[v] = tot ++;
}

void dfs(int u) {
    static int counter = 0;
    int child = 0;
    low[u] = dfn[u] = ++counter;
    for (int i = head[u]; i + 1; i = edge[i].nxt) {
        if(belong[edge[i].id] != -1) continue;
        int v = edge[i].v;
        if(!dfn[v]) {
            child ++;
            par[v] = u;
            Stack[++ top] = edge[i].id;
            dfs(v);
            low[u] = min(low[v], low[u]);
            if((par[u] == -1 && child > 1) || (par[u] != -1 && low[v] >= dfn[u])) {
                cnt ++;
                int minn = INF;
                do{
                    belong[Stack[top]] = cnt;
                    minn = min(minn, Stack[top]);
                }while(Stack[top--] != edge[i].id);
                Min[cnt] = minn;
            }
        }else if(par[u] != v) {
            Stack[++ top] = edge[i].id;
            low[u] = min(low[u], dfn[v]);
        }
    }
}

int main()
{
    init();
    cin >> n >> m;
    for (int i = 1; i <= m; i ++) {
        int u, v;
        cin >> u >> v;
        addEdge(u, v, i);
    }
    dfs(1);
    cnt ++;
    int minn = INF;
    while(top != 0) {
        belong[Stack[top]] = cnt;
        minn = min(minn, Stack[top]);
        top --;
    }
    Min[cnt] = minn;
    cout << cnt << endl;
    for (int i = 1; i <= m; i ++) {
        cout << Min[belong[i]] << " ";
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/henu_jizhideqingwa/article/details/85207304
今日推荐