版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/pengwill97/article/details/81951576
题意
根据每个点所在的边双连通分量,输出其组内最小的顶点编号。
题解
Tarjan算法。
2边dfs即可。
代码
#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], n, m, tot;
int dfn[nmax], low[nmax], dfs_clock, bcc, thisans;
int ans[nmax];
struct edge{
int to, nxt;
bool isbridge;
}e[nmax<<1];
void add_edge(int u, int v) {
e[tot].to = v;
e[tot].nxt = head[u];
head[u] = tot++;
}
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(!dfn[v]) {
// S.push(make_pair(u, v));
tarjan(v, u);
low[u] = min(low[u], low[v]);
if(low[v] > dfn[u]) {
e[i].isbridge = true;
e[i^1].isbridge = true;
// for(;;) {
// pii temp = S.top;
// S.pop();
// if(temp.first == u && temp.second == v || temp.first == v && temp.second == u) {
// break;
// }
//
// }
bcc ++;
}
} else if(v != fa) {
low[u] = min(low[u], dfn[v]);
}
}
}
void dfs(int u, int fa) {
ans[u] = thisans;
for(int i = head[u]; i != -1; i = e[i].nxt) {
int v = e[i].to;
if(!e[i].isbridge && v != fa && !ans[v])
dfs(v, u);
}
}
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);
add_edge(v, u);
}
for(int i = 1; i <= n; ++i) {
if(!dfn[i])
tarjan(i, -1);
}
for(int i = 1; i <= n; ++i) {
if(!ans[i]) {
thisans = i;
dfs(i, -1);
}
}
printf("%d\n", bcc+1);
for(int i = 1; i <= n; ++i) {
printf("%d ", ans[i]);
}
printf("\n");
return 0;
}