回家 (无向图割点)
程序员文章站
2022-06-03 16:55:10
...
思路:
一是要是割点,而是要分开1和n。
我们通过判断一个割点的儿子能不能到达n,因为割点的儿子跟1是不相连的(从1开始的dfs)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
#define LL long long
#define N 200010
#define M 400010
using namespace std;
int n, m, idc = 0, idx = 0;
int head[N], vis[N], exi[N];
int dfn[N], low[N], iscut[N], ans[N];
inline int read(){
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9'){ x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
struct Edge{
int to, nxt;
}ed[M << 1];
inline void adde(int u, int v){
ed[++idc].to = v;
ed[idc].nxt = head[u];
head[u] = idc;
}
inline int dfs(int u, int f){
if(vis[u] == 1) return exi[u];
vis[u] = 1;
if(u == n) {
vis[u] = 1; exi[u] = 1;
return 1;
}
for(register int k = head[u]; k; k = ed[k].nxt){
int v = ed[k].to;
if(v == f || v == u) continue;
if( dfs(v, u) ){
exi[u] = 1;
}
}
return exi[u];
}
stack <int> state;
inline void tarjan(int u, int fa){
dfn[u] = low[u] = ++idx;
vis[u] = 1;
if(u == n) exi[u] = 1;
state.push(u);
for(register int i=head[u]; i; i=ed[i].nxt){
int v = ed[i].to;
if( !vis[v] ){
tarjan(v, u);
exi[u] |= exi[v];
low[u] = min(low[u], low[v]);
if(low[v] >= dfn[u] && exi[v]){/*用儿子判*/
iscut[u] = 1;//u是割点
}
}
else if( dfn[v] < dfn[u] && v != fa ){
low[u] = min(low[u], dfn[v]);
}
}
}
inline void init(){
memset(head, 0, sizeof(head));
memset(ed, 0, sizeof(ed));
memset(vis, 0, sizeof(vis));
memset(exi, 0, sizeof(exi));
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
memset(iscut, 0, sizeof(iscut));
idc = 0; idx = 0;
}
int main(){
freopen ("home.in", "r", stdin);
freopen ("home.out", "w", stdout);
int T; scanf("%d", &T);
while ( T-- ){
init();
scanf ("%d%d", &n, &m);
for(register int i=1; i<=m; i++){
int u = read(), v = read();
adde(u, v); adde(v, u);
}
tarjan( 1, 1 );
int cc = 0;
for(register int i=2; i<n; i++){
if( iscut[i] == 1 ) ans[++cc] = i;
}
printf("%d\n", cc);
for(register int i=1; i<cc; i++) printf("%d ", ans[i]);
if( cc ) printf("%d\n", ans[cc]);
else printf("\n");/**/
}
}
上一篇: 中国什么时候开始有白酒的?中国酒文化